- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以下代码可以编译,因为我假设 parent
的 Object<Parent, T, Rest...>
本身没有 parent 。
template <typename Parent, typename T, typename... Rest>
struct Object {
T item; // T is item's type, while Parent is parent's item's type.
Object<T, Rest...>* child; // child's item type is the first type from Rest...
Object<void, Parent, T, Rest...>* parent;
Object(const T& t) : item(t) {}
void setChild (Object<T, Rest...>* c) {
child = c;
child->setParent(this);
}
void setParent (Object<void, Parent, T, Rest...>* p) {parent = p;}
};
template <typename Parent, typename T>
struct Object<Parent, T> { // Has no child.
T item;
Object<void, Parent, T>* parent;
Object(const T& t) : item(t) {}
void setParent (Object<void, Parent, T>* p) {parent = p;}
};
template <typename... Args>
using ObjectWithNoParent = Object<void, Args...>;
int main() {
ObjectWithNoParent<int, char, double> object(2);
Object<int, char, double> child('r');
object.setChild(&child);
Object<char, double> grandChild(3.5);
// child.setChild(&grandChild); // Want this line to work.
}
我可以使用什么解决方法来替换类型 void
与一般类型?
最佳答案
编译器必须能够分辨出一个参数包从哪里开始,另一个参数包从哪里结束。为此,您所要求的直接是不可能的,但有一个解决方法:使用另一个可变参数模板作为“包分隔符”。
我们的目标是支持这样的类型:
Object<pack<A, B>, C, pack<D, E>> foo;
在这种情况下,C
是foo
的值类型,它将具有以下相关类型:
Object<pack<A>, B, pack<C, D, E>> foo_parent;
Object<pack<A, B, C>, D, pack<E>> foo_child;
无父类型的第一包是空的,无子类型的第二包是空的。
由于您不能通过可变参数“向后递归”,所以这很复杂,因此具有父级的类型会有点混淆。 (不幸的是,template <typename... Types, typename Last> struct foo
方法不起作用,因为参数包必须是模板参数列表中的最后。)我们需要更多的助手来获取并“剥离”可变参数包中的最后一个类型(将 pack<A, B, C>
更改为 pack<A, B>
)。
我们将从声明 pack
开始:
// Helper template; needs no definition since we never instantiate it.
template <typename...> struct pack;
现在我们需要一个助手来获取包中的最后一个类型;给出pack<A, B, C>
它应该让我们获得C
.为此,我们定义了一个元函数,该函数将从包的开头删除类型,直到只剩下一个。
// Helper to allow us to obtain the last type from a pack.
template <typename> struct last_type_in_pack;
template <typename T>
struct last_type_in_pack<pack<T>>
{
typedef T type;
};
template <typename First, typename... Types>
struct last_type_in_pack<pack<First, Types...>>
: public last_type_in_pack<pack<Types...>> { };
现在我们需要助手来转 pack<A, B, C>
进入pack<A, B>
.我们将在为对象构建父类型时使用它。这个元函数从模板参数开始工作 pack<>, pack<A, B, C>
并将最左侧的右侧包移动到左侧包中最右侧的位置。当最右边的包还剩下一种类型时,最左边的包就是我们的最终类型。
如果这很难遵循,请执行以下步骤:
pack<>, pack<A, B, C>
开始.正确的包有不止一个元素,所以我们继续。pack<A>, pack<B, C>
.正确的包装仍然有不止一种元素。pack<A, B>, pack<C>
.右边的包有一个元素,所以左边的包是我们的最终类型。实现:
// We need another helper to allow us to "peel off" the last type from a pack,
// turning pack<A, B, C> into pack<A, B> for example.
template <typename, typename> struct remove_last_type_from_pack_impl;
template <typename... Types, typename LastType>
struct remove_last_type_from_pack_impl<pack<Types...>, pack<LastType>>
{
typedef pack<Types...> type;
};
template <typename... TS1, typename T2, typename... TS2>
struct remove_last_type_from_pack_impl<pack<TS1...>, pack<T2, TS2...>>
: public remove_last_type_from_pack_impl<pack<TS1..., T2>, pack<TS2...>> { };
template <typename>
struct remove_last_type_from_pack;
template <typename... Types>
struct remove_last_type_from_pack<pack<Types...>>
: public remove_last_type_from_pack_impl<pack<>, pack<Types...>> { };
现在我们实际申报Object
.我们没有定义它,因为我们将为每个预期的实例化提供部分特化。如果有人试图将此模板与我们不支持的参数一起使用,他们只会收到“不完整类型”错误,这正是我们想要的。
template <typename...> struct Object;
部分特化允许“双端”包,并且需要至少一种父类型和一种子类型。 (FirstParent
的存在只是为了强制当第一个包为空时此部分特化将不匹配。)
template <typename FirstParent, typename... ParentTypes,
typename T,
typename FirstChild, typename... ChildTypes>
struct Object<pack<FirstParent, ParentTypes...>, T, pack<FirstChild, ChildTypes...>>
{
// We'll shift the packs around T to define our child and parent types:
typedef Object<pack<FirstParent, ParentTypes..., T>,
FirstChild,
pack<ChildTypes...>> child_type;
typedef Object<
typename remove_last_type_from_pack<pack<FirstParent, ParentTypes...>>::type,
typename last_type_in_pack<pack<FirstParent, ParentTypes...>>::type,
pack<T, FirstChild, ChildTypes...>> parent_type;
T item;
child_type * child;
parent_type * parent;
Object(T const & t) : item(t) { }
Object(T && t) : item(std::move(t)) { }
};
现在我们需要针对无 parent 和无子女的特化。
parent-less类型比较简单:
template <typename T, typename FirstChild, typename... ChildTypes>
struct Object<pack<>, T, pack<FirstChild, ChildTypes...>>
{
typedef Object<pack<T>, FirstChild, pack<ChildTypes...>> child_type;
T item;
child_type * child;
Object(T const & t) : item(t) { }
Object(T && t) : item(std::move(t)) { }
};
现在是无子类型。和以前一样,FirstParent
只是确保我们至少有一个父类型。
我们必须进行相同的操作才能获得父类型。
template <typename FirstParent, typename... ParentTypes, typename T>
struct Object<pack<FirstParent, ParentTypes...>, T, pack<>>
{
typedef Object<
typename remove_last_type_from_pack<pack<FirstParent, ParentTypes...>>::type,
typename last_type_in_pack<pack<FirstParent, ParentTypes...>>::type,
pack<T>> parent_type;
T item;
parent_type * parent;
Object(T const & t) : item(t) { }
Object(T && t) : item(std::move(t)) { }
};
注意此时Object<pack<>, T, pack<>>
无法实例化,因为没有与之匹配的特化,并且未定义基本模板。这种类型并没有多大意义,IMO,但你可以专门化 Object
如果你愿意的话:
template <typename T>
struct Object<pack<>, T, pack<>>
{
T item;
Object(T const & t) : item(t) { }
Object(T && t) : item(std::move(t)) { }
};
如果你还想要你的 ObjectWithNoParent
模板别名,这是现在的样子:
template <typename Arg, typename... Rest>
using ObjectWithNoParent = Object<pack<>, Arg, pack<Rest...>>;
(Here is a sample 并没有做太多,但它确实表明它可以编译并断言父类型和子类型是我们所期望的。)
关于c++ - Variadic 模板双端包解决方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28072893/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!