[英]C++ Template Variadic Class Constructor working with Parameter Pack but functions not
[英]Unpacking parameter pack of args into the constructor of each class defined in a variadic template
我正在尝试创建一个继承自多个类的类(由可变参数模板定义),并且对于每个类,将args的相同参数包传递给每个类的构造函数。 但是,似乎我无法解压缩类的可变参数模板和args的参数包。
我有一节课:
template<class... __Policies>
class GenericPolicyAdapter : public __Policies...{
使用构造函数:
template<class... __Args>
GenericPolicyAdapter( __Args... args ) : __Policies( args... ){
并测试:
GenericPolicyAdapter<T1,T2> generic_policy_adapter( arg1, arg2, arg3 );
gcc失败了:
error: type ‘__Policies’ is not a direct base of ‘GenericPolicyAdapter<T1,T2>’
其中__Policies = T1, T2
澄清一下,我基本上是想做:
GenericPolicyAdapter : public T1, public T2
{
public:
template<class... __Args>
GenericPolicyAdapter( __Args... args ) : T1( args... ), T2( args... ){}
};
但是从__Policies
推断出T1
和T2
有任何想法吗? 似乎gcc将__Policies
视为单一类型而不是类型列表。 提前致谢!
编辑:
我应该澄清一下,我正在使用gcc / g ++ 4.4.5。
Howard Hinnant的建议是:
template<class... __Args>
GenericPolicyAdapter( __Args... args )
: __Policies( args...)...
{}
但是,使用gcc / g ++ 4.4.5时,这会invalid use of pack expansion expression
。 这非常适合在OSX / clang中使用,但有没有办法在gcc / g ++中执行此操作?
“ ...
”很像“ typename
”。 你必须继续积极地将它洒在周围,直到编译完成。 :-)
template<class... __Policies>
class GenericPolicyAdapter
: public __Policies...
{
public:
template<class... __Args>
GenericPolicyAdapter( __Args... args )
: __Policies( args...)...
{}
};
struct T1
{
T1(int, int, int) {}
};
struct T2
{
T2(int, int, int) {}
};
int main()
{
GenericPolicyAdapter<T1,T2> generic_policy_adapter( 1, 2, 3 );
}
来自http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
14.5.3变量模板[temp.variadic]
5名称显示在包扩展模式中的参数包通过该包扩展进行扩展。 参数包名称的外观仅通过最里面的封装包扩展来扩展。 包扩展的模式应命名一个或多个未通过嵌套包扩展扩展的参数包。 通过包扩展扩展的所有参数包应具有相同数量的参数。 未展开的参数包名称的外观是不正确的。 [例如:
template<typename...> struct Tuple {}; template<typename T1, typename T2> struct Pair {}; template<class ... Args1> struct zip { template<class ... Args2> struct with { typedef Tuple<Pair<Args1, Args2> ... > type; }; }; typedef zip<short, int>::with<unsigned short, unsigned>::type T1; // T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>> typedef zip<short>::with<unsigned short, unsigned>::type T2; // error: different number of arguments specified for Args1 and Args2 template<class ... Args> void g(Args ... args) { f(const_cast<const Args*>(&args)...); // OK: “Args” and “args” are expanded f(5 ...); // error: pattern does not contain any parameter packs f(args); // error: parameter pack “args” is not expanded f(h(args ...) + args ...); // OK: first “args” expanded within h, second // “args” expanded within f }
- 末端的例子]
我认为f(h(args ...) + args ...);
可能是你得到的最接近的标准例子。
请注意,如果你做了:
template<class... __Policies>
class GenericPolicyAdapter
: public __Policies...
{
public:
template<class... __Args>
GenericPolicyAdapter( __Args... args )
: __Policies(args)... // See the missing '...' ?
{}
};
您将拉出构造函数参数列表的单个arg,并将它们应用于基础构造函数。 关键是在展开args
后扩展__Policies
。
正如上面评论中所提到的,gcc在可变参数模板支持方面相当薄弱。 特别是涉及参数包扩展时。 Gcc 4.6甚至无法将包扩展到固定长度列表。
以下代码是一种可能的解决方法,它基于一种更复杂的方法来解决我通常使用的那些限制。 它只能在svn的最新gcc上编译:
#include <iostream>
template<class T>
struct derive : T
{
template<class... A>
derive( A... a ) :
T(a...)
{
}
};
template<class X, class... T>
struct deriver;
template<class X>
struct deriver<X> :
derive<X>
{
template<class... A>
deriver( A... a ) :
derive<X>(a...)
{
}
};
template<class X, class... T>
struct deriver :
derive<X>, deriver<T...>
{
template<class... A>
deriver( A... a ) :
derive<X>(a...), deriver<T...>(a...)
{
}
};
template<class... __Policies>
class GenericPolicyAdapter
: public deriver<__Policies...>
{
public:
template<class... __Args>
GenericPolicyAdapter( __Args... args )
: deriver<__Policies...>( args...)
{}
};
#define BARK std::cout << __PRETTY_FUNCTION__ << "\n"
struct T1
{
T1(int, int, int) {BARK;}
};
struct T2
{
T2(int, int, int) {BARK;}
};
int main()
{
GenericPolicyAdapter<T1,T2> generic_policy_adapter( 1, 2, 3 );
}
所有发布的gccs都会扼杀:
sorry, unimplemented: cannot expand 'T ...' into a fixed-length argument list
这可能也可以通过更加间接的方式解决,但这应该是一个很好的起点(取决于你想要多少便携性)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.