Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a variadic template match a non-variadic template parameter?

Consider the following snippet:

template<template<class> class T,class U>
struct apply
{
     typedef T<U> type;
};

typedef apply<std::tuple,int>::type tuple_of_one_int; //Should be std::tuple<int>

GCC 4.8.2. says:

type/value mismatch at argument 1 in template parameter list for [...] struct apply
expected a template of type ‘template<class> class T’, got ‘template<class ...> class std::tuple’

Which basically means that a variadic template like std::tuple is not a valid template argument for T in apply.

Is this a GCC bug or does the standard mandates this behaviour?

like image 412
sbabbi Avatar asked Dec 03 '13 16:12

sbabbi


People also ask

Can we pass non-type parameters to templates?

Template non-type arguments in C++It is also possible to use non-type arguments (basic/derived data types) i.e., in addition to the type argument T, it can also use other arguments such as strings, function names, constant expressions, and built-in data types.

What is the use of Variadic templates?

With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.

Which of the following are valid reasons for using Variadic templates in C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration. However, variadic templates help to overcome this issue.

What is a Variadic template C++?

A variadic template is a class or function template that supports an arbitrary number of arguments. This mechanism is especially useful to C++ library developers: You can apply it to both class templates and function templates, and thereby provide a wide range of type-safe and non-trivial functionality and flexibility.


2 Answers

Someone correct me if I'm wrong but it seems like it's correct from this quote:

3 A template-argument matches a template template-parameter (call it P) when each of the template parameters in the template-parameter-list of the template-argument’s corresponding class template or [FI 11] template aliasalias template (call it A) matches the corresponding template parameter in the template-parameter-list of P

A (the given template) has to match each of it's templates parameters to P's the template template.

From the second part of the section we learn the restriction doesn't apply in the reverse, meaning a template template containing a parameter pack can match anything.

When P’s template-parameter-list contains a template parameter pack (14.5.3), the template parameter pack will match zero or more template parameters or template parameter packs in the template-parameter- list of A with the same type and form as the template parameter pack in P

As you probably already knew the way to make it work is

template<template<class> class T,class U>                                       
struct apply                                                                       
{                                                                                  
         typedef T<U> type;                                                        
};                                                                                 

template<class T> using tuple_type  = std::tuple<T>;
typedef apply<tuple_type,int>::type tuple_of_one_int;                          

The c++11 standard also has an equivalent example to yours.

template <class ... Types> class C { /∗ ... ∗/ };

template<template<class> class P> class X { /∗ ... ∗/ };

X<C> xc; //ill-formed: a template parameter pack does not match a template parameter  

The last comment completely describes your situation, class C would be the equivalent of std::tuple in this case.

like image 61
aaronman Avatar answered Nov 02 '22 23:11

aaronman


Your code is ill-formed, there is equivalent example in the standard (under 14.3.3/2):

...
template <class ... Types> class C { /∗ ... ∗/ };

template<template<class> class P> class X { /∗ ... ∗/ };
...
X<C> xc; // ill-formed: a template parameter pack does not match a template parameter
...
like image 42
zch Avatar answered Nov 03 '22 01:11

zch