C++ variadic template template argument that matches any kind of parameters

Your interesting construct has two levels with variadic templates.

  • An outer variadic template parameter list TemplateP & Sizes for a function template
  • An inner parameter pack as the template parameters of your template template parameter TemplateT, a class template

First, let’s look at the inner TemplateT class: why can the ellipsis operator not not match something like TemplateT< int, 2 >? Well, the standard defines variadic templates in §14.5.3 as

template<class ... Types> struct Tuple { };
template<T ...Values> struct Tuple2 { };

where the template argument pack in the first case may only match types and in the second version only values of type T. In particular,

Tuple < 0 >    error;  // error, 0 is not a type!
Tuple < T, 0 > error2; // T is a type, but zero is not!
Tuple2< T >    error3; // error, T is not a value
Tuple2< T, 0 > error4; // error, T is not a value

are all malformed. Furthermore, it is not possible to fall back to something like

template<class ... Types, size_t ...Sizes> struct Tuple { };

because the standard states in §14.1.11:

If a template-parameter of a primary class template or alias template is a template parameter pack, it
shall be the last template-parameter. A template parameter pack of a function template shall not be followed
by another template parameter unless that template parameter can be deduced from the parameter-type-list
of the function template or has a default argument (14.8.2).

In other words, for class templates only one variadic parameter pack may appear in the definition. Therefore the above (double)-variadic class definition is malformed. Because the inner class always needs such a combination, it is impossible to write something as general as you conceived.


What can be rescued? For the outer function template, some shards can be put together, but you won’t like it. As long as the second parameter pack can be deduced from the first, two parameter packs may appear (in a function template). Therefore, a function such as

template < typename... Args, size_t... N > void g(const std::array< Args, N > &...arr);
g(std::array< double, 3 >(), std::array< int, 5>());

is allowed, because the integer values can be deduced. Of course, this would have to be specialized for every container type and is far from what you had imagined.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)