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

use*_*370 43 c++ templates variadic-templates c++11

如果我定义了一个struct模板Bar,它接受一个模板参数:

template <template <int,bool,char> class>
struct Bar {};
Run Code Online (Sandbox Code Playgroud)

我可以使用以下struct模板对其进行实例化Zod:

template <int,bool,char> struct Zod {};
Bar<Zod> a;
Run Code Online (Sandbox Code Playgroud)

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

struct GHI {
  template <int,bool,char>
  struct JKL {};
};
Bar <GHI::JKL> b;
Run Code Online (Sandbox Code Playgroud)

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

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

Bar<ABC<int,bool,char>::DEF> c;
Run Code Online (Sandbox Code Playgroud)

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

T.C*_*.C. 5

让我们给DEF的参数包一个名称以便于参考:

template <typename ...Ts>
struct ABC {
  template <Ts ... Values>
  struct DEF {};
};
Run Code Online (Sandbox Code Playgroud)

这里的关键点在于,通过[temp.param]/P15,Ts... Values两者的一包扩展Ts和参数组的声明Values.

如果一个模板参数是[...]一个参数声明,声明一个参数包(8.3.5),那么模板参数是一个模板参数包(14.5.3).模板参数包是一个 参数声明,其类型包含一个或多个未展开的参数包,是包扩展.

由于DEF采用非类型参数包,它与不带包的模板模板参数([temp.arg.template]/p3)不匹配:

template-argument的对应类模板或别名模板A 的template-parameter-list中的每个模板参数与template-parameter-list中对应的模板参数匹配时,template-argument匹配模板template-parameter P. P.两个模板参数匹配,如果它们属于同一类型(类型,非类型,模板),对于非类型模板参数 s,它们的类型是等价的(14.5.6.1),对于模板模板参数 s ,每个相应的 模板参数 s递归匹配.当P的template-parameter-list包含模板参数包(14.5.3)时,模板参数包将匹配A 的template-parameter-list中的零个或多个模板参数或模板参数包,其 类型和形式与P中的模板参数包(忽略这些模板参数是否为模板参数包).

可以肯定的,Values是相当奇怪的包装-对于每一个专业化ABC,Values必须包含的参数固定数量的-但根据目前的规则,它仍然是一个包,所以包的规则.