If I define a struct
template Bar
which accepts a template argument:
template <template <int,bool,char> class> struct Bar {};
I can instantiate it using a struct
template such as Zod
:
template <int,bool,char> struct Zod {}; Bar<Zod> a;
I can also instantiate it using a nested struct
template such as JKL
:
struct GHI { template <int,bool,char> struct JKL {}; }; Bar <GHI::JKL> b;
Why can't I instantiate Bar
using a nested variadic struct
template such as DEF
?:
template <typename ...Ts> struct ABC { template <Ts ...> struct DEF {}; }; Bar<ABC<int,bool,char>::DEF> c;
G++ 4.9.2 complains of a type/value mismatch; while Clang 3.4.2's error reports that the template template argument has different template parameters than its corresponding template template parameter.
Let's give DEF's parameter pack a name for ease of reference:
template <typename ...Ts> struct ABC { template <Ts ... Values> struct DEF {}; };
The key point here is that by [temp.param]/p15, Ts... Values
is both a pack expansion of Ts
and a declaration of a parameter pack Values
.
If a template-parameter is [...] a parameter-declaration that declares a parameter pack (8.3.5), then the template-parameter is a template parameter pack (14.5.3). A template parameter pack that is a parameter-declaration whose type contains one or more unexpanded parameter packs is a pack expansion.
Since DEF
takes a non-type parameter pack, it doesn't match a template template parameter that doesn't take packs ([temp.arg.template]/p3):
A template-argument matches a template template-parameter P when each of the template parameters in the template-parameter-list of the template-argument’s corresponding class template or alias template A matches the corresponding template parameter in the template-parameter-list of P. Two template parameters match if they are of the same kind (type, non-type, template), for non-type template-parameters, their types are equivalent (14.5.6.1), and for template template-parameters, each of their corresponding template-parameters matches, recursively. 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 (ignoring whether those template parameters are template parameter packs).
To be sure, Values
is rather weird for packs - for every specialization of ABC
, Values
must contain a fixed number of arguments - but under the current rules it's still a pack, so the rules for packs apply.
Like Barry said before about:
ABC<int,bool,char>::DEF<4,true,'c'> foo
And make a try and worked on Coliru online compiler gcc 5.1 c++14 in this site Compiler:
#include <iostream> template <template <int,bool,char> class> struct Bar {}; template <int,bool,char> struct Zod {}; Bar<Zod> a; struct GHI { template <int,bool,char> struct JKL {}; }; Bar <GHI::JKL> b; template <template <typename... Ts> class> struct Base {}; template<typename... Ts> struct Floor {}; Base<Floor> c; template <typename... Ts> struct ABC { template <Ts... val> struct DEF {}; }; ABC<int,bool,char>::DEF<4,true,'c'> foo;
I made a search and found this Template parameter list.
Pack expansion may appear in a template parameter list:
template<typename... T> struct value_holder { template<T... Values> // expands to a non-type template parameter struct apply { }; // list, such as <int, char, int(&)[5]> };
where i tested some stuff in the run code compiler at: http://en.cppreference.com/w/cpp/language/parameter_pack but also i found this Ellipses and Variadic Templates in visual studio 2013: https://msdn.microsoft.com/en-us/library/dn439779.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With