【发布时间】:2009-10-02 20:03:51
【问题描述】:
我记得看到过这样的事情:
template <ListOfTypenames>
class X : public ListOfTypenames {};
也就是说,X 继承自作为模板参数传递的可变长度类型名列表。当然,这段代码是假设的。
不过,我找不到任何参考资料。是否可以?是 C++0x 吗?
【问题讨论】:
标签: c++ templates c++11 variable-length
我记得看到过这样的事情:
template <ListOfTypenames>
class X : public ListOfTypenames {};
也就是说,X 继承自作为模板参数传递的可变长度类型名列表。当然,这段代码是假设的。
不过,我找不到任何参考资料。是否可以?是 C++0x 吗?
【问题讨论】:
标签: c++ templates c++11 variable-length
你可以在当前的 C++ 中做到这一点。您为模板提供“足够大”数量的参数,并为它们提供默认值:
class nothing1 {};
class nothing2 {};
class nothing3 {};
template <class T1 = nothing1, class T2 = nothing2, class T3 = nothing3>
class X : public T1, public T2, public T3 {};
或者您可以变得更复杂并使用递归。首先你前向声明模板:
class nothing {};
template <class T1 = nothing, class T2 = nothing, class T3 = nothing>
class X;
然后你专门针对所有参数都是默认的情况:
template <>
class X<nothing, nothing, nothing> {};
然后您正确定义通用模板(之前您只前向声明):
template <class T1, class T2, class T3>
class X : public T1, public X<T2, T3>
注意在基类中,你继承了 X,但你错过了第一个参数。所以他们都沿着一个地方滑动。最终它们都将成为默认值,并且专门化将启动,它不会继承任何东西,从而终止递归。
更新:只是有一种奇怪的感觉,我以前发布过类似的东西,and guess what...
【讨论】:
X<T1, T2, T3>继承X<T1, T2, T3>会发生什么?无限深度!但是跳过第一个参数,意味着我们继承了X<T2, T3, nothing>,后者又继承了X<T3, nothing, nothing>,后者又继承了X<nothing, nothing, nothing>。对于那种“一无所有”的情况,有一个不继承任何东西的专业化,所以它停止了。顺便说一句,在递归示例的最后一部分中,我最初没有使用T1,所以我添加了它的继承以使其与非递归示例一致(否则它实际上并没有回答问题!)
T1,而是继承W<T1>,其中W是一个包装类,可能带有一个typedef成员,让你得到类型参数。
听起来您指的是 C++0x Variadic Templates。您也可以使用来自 Loki 的 Alexandrescu 的 TypeList 构造来实现相同的效果。
我相信有问题的可变参数模板语法如下所示。
template <typename...T>
class X : public T... {};
【讨论】:
public T... {};
正如其他人已经回答的那样,可变参数模板是下一个标准的一部分,但可以在当前的 C++ 中进行模拟。一种方便的工具是使用Boost.MPL 库。在您的代码中,您编写了一个模板参数(我们将其命名为“Typelist”),模板的用户将 typelist 包装在 MPL 序列中。示例:
#include "YourType.h"
#include "FooBarAndBaz.h"
#include <boost/mpl/vector.hpp>
YourType<boost::mpl::vector<Foo, Bar, Baz> > FooBarBaz;
在“YourType”的实现中,可以通过各种元函数访问Typelist中的元素。例如,at_c<Typelist, N> 是列表的第 N 个元素。另一个例子,你问题中的“X”类可以用inherit_linearly写成:
//Warning: Untested
namespace bmpl = boost::mpl;
template<class Typelist>
class X : bmpl::inherit_linearly<Typelist, bmpl::inherit<bmpl::_1, bmpl::_2> >::type
{
...
};
【讨论】:
可变数量的模板是下一个 C++ 标准的一部分。但是,如果您使用 GCC(从 4.3 版开始),您可以体验一下。这是list of available C++0x features in GCC。您正在寻找可变参数模板。
顺便说一句,如果你需要关于如何实现 Earwicker 描述的继承机制的正式参考,它在书 C++ Templates 上。
【讨论】: