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

后端 未结 3 1188
野的像风
野的像风 2021-01-30 16:38

I was wondering if it\'s possible to write a template function that can take any other arbitrary template as a parameter and properly match the template name (i.e. not just the

3条回答
  •  既然无缘
    2021-01-30 17:34

    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 struct Tuple { };
    template 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 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.

提交回复
热议问题