为什么这个嵌套可变参数模板是无效的参数?

如果我定义一个接受模板参数的struct模板Bar

 template <template <int,bool,char> class> struct Bar {}; 

我可以使用一个struct模板(如Zod来实例化它:

 template <int,bool,char> struct Zod {}; Bar<Zod> a; 

我也可以使用嵌套的struct模板(如JKL来实例化它:

 struct GHI { template <int,bool,char> struct JKL {}; }; Bar <GHI::JKL> b; 

为什么我不能使用嵌套可变参数struct模板(如DEF ?)实例化Bar

 template <typename ...Ts> struct ABC { template <Ts ...> struct DEF {}; }; Bar<ABC<int,bool,char>::DEF> c; 

G ++ 4.9.2抱怨types/值不匹配; 而Clang 3.4.2的错误报告模板模板参数具有不同于其对应的模板参数的模板参数。

让我们给DEF的参数包一个名字,以方便参考:

 template <typename ...Ts> struct ABC { template <Ts ... Values> struct DEF {}; }; 

这里的关键是通过[temp.param] / p15, Ts... Values 既是 Ts的包扩展,也是参数包Values的声明。

如果模板参数是声明参数包(8.3.5)的参数声明,则模板参数是模板参数包(14.5.3)。 作为参数声明的模板参数包,其types包含一个或多个未展开的参数包是一个包扩展。

由于DEF采用非types参数包,因此它不匹配不包含包的模板模板参数([temp.arg.template] / p3):

当模板参数对应的类模板或别名模板A的模板参数列表中的每个模板参数与模板参数列表中对应的模板参数匹配时,模板参数与模板模板参数 P匹配如果两个模板参数属于同一types(types,非types,模板),对于非types的模板参数 s,它们的types是等价的(14.5.6.1),对于模板模板参数 s ,每个相应的模板参数都是recursion匹配的。 当P的模板参数列表包含一个模板参数包(14.5.3)时,模板参数包将匹配A的模板参数列表中的零个或多个模板参数或模板参数包,其格式和forms与P中的模板参数包(忽略这些模板参数是否是模板参数包)。

可以肯定的是,对于数据包来说, Values是相当奇怪的 – 对于ABC每一个专业化来说, Values必须包含固定数量的参数 – 但是在目前的规则下它仍然是一个包,所以适用于包的规则。

就像巴里之前所说的:

 ABC<int,bool,char>::DEF<4,true,'c'> foo 

并试一试Coliru在线编译gcc 5.1 c ++ 14在本站编译 :

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

我做了一个search,发现这个模板参数列表。

包扩展可能出现在模板参数列表中:

  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]> }; 

在那里我在运行代码编译器testing了一些东西: http ://en.cppreference.com/w/cpp/language/parameter_pack,但我也发现这个椭圆和Variadic模板在Visual Studio 2013中: https ://msdn.microsoft .COM / EN-US /库/ dn439779.aspx