Unpacking the args parameter package in the constructor of each class defined in the variational template

I am trying to create a class that inherits from several classes (as defined by a variational pattern), and for each class passes the same package of args parameters to the constructor of each class. However, it seems that I cannot unzip both the variational class template and the args parameter package.

I have a class:

template<class... __Policies> class GenericPolicyAdapter : public __Policies...{ 

With constructor:

 template<class... __Args> GenericPolicyAdapter( __Args... args ) : __Policies( args... ){ 

and test:

 GenericPolicyAdapter<T1,T2> generic_policy_adapter( arg1, arg2, arg3 ); 

gcc crash:

 error: type '__Policies' is not a direct base of 'GenericPolicyAdapter<T1,T2>' 

where __Policies = T1, T2

To clarify, I try:

 GenericPolicyAdapter : public T1, public T2 { public: template<class... __Args> GenericPolicyAdapter( __Args... args ) : T1( args... ), T2( args... ){} }; 

but with T1 and T2 derived from __Policies

Any ideas? __Policies seems to treat __Policies as a single type, not a list of types. Thanks in advance!


Edit:

I must clarify that I am using gcc / g ++ 4.4.5.

Howard Hinnant's proposal was to make:

 template<class... __Args> GenericPolicyAdapter( __Args... args ) : __Policies( args...)... {} 

However, with gcc / g ++ 4.4.5, this gives invalid use of pack expansion expression . It's great that this works in OSX / clang, but is there a way to do this in gcc / g ++?

+4
source share
3 answers

" ... " is very similar to " typename ". You just need to keep aggressively spraying it until everything compiles. :-)

 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 ); } 
+16
source

From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf

14.5.3 Variadic Templates [Temp.variadic]

5 The package of parameters, whose name is displayed in the package extension template, is expanded by the extension of this package. The appearance of the name of the parameter package is expanded only with the help of the internal extension of the package. A package extension pattern must specify one or more parameter packages that are not expanded by the extension of the nested package. All parameter packages extended by the package extension must have the same number of arguments. The appearance of the name of the parameter package, which is not extended, is poorly formed. [Example:

 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 } 

-end example]

I think f(h(args ...) + args ...); may be the closest standard example you get.

Please note that if you have done:

 template<class... __Policies> class GenericPolicyAdapter : public __Policies... { public: template<class... __Args> GenericPolicyAdapter( __Args... args ) : __Policies(args)... // See the missing '...' ? {} }; 

You would pull one argument from the list of constructor options and apply them to the base constructors. The key is to deploy __Policies after the args extension.

+6
source

As mentioned in the comment above, gcc is pretty weak at supporting the variation pattern per day. Especially when it comes to expanding the package of parameters. Gcc 4.6 cannot even expand packages into fixed-length lists.

The following code is a possible workaround based on a much more complicated way of dealing with the limitations that I usually use. It will only compile on the very recent gcc from svn:

 #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 ); } 

All released gccs will throttle this with:

 sorry, unimplemented: cannot expand 'T ...' into a fixed-length argument list 

which may also have worked around in an even more indirect way, but this should be a good starting point (depending on what kind of mobility you want).

0
source

All Articles