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

时间:2015-05-17 22:52:17

标签: c++ templates c++11 variadic-templates

如果我定义了一个接受模板参数的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;

为什么我无法使用嵌套的可变参数Bar模板struct来实例化DEF?:

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

Bar<ABC<int,bool,char>::DEF> c;

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

2 个答案:

答案 0 :(得分:5)

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

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

这里的关键点是,通过[temp.param] / p15,Ts... Values 两者Ts的扩展和参数包{{}的声明1}}。

  

如果 template-parameter 参数声明,   声明参数包(8.3.5),然后 template-parameter 是一个   模板参数包(14.5.3)。模板参数包是一个    parameter-declaration 其类型包含一个或多个未展开的参数包是包扩展。

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

  

template-argument 匹配模板 template-parameter P.   中的每个模板参数    template-argument 对应的类模板的 template-parameter-list 或别名模板A匹配相应的模板   P.模板参数列表中的参数。两个模板参数   如果它们属于同一类型(类型,非类型,模板),则匹配   非类型模板参数,它们的类型是等价的(14.5.6.1),   对于模板模板参数,它们各自对应    template-parameter 以递归方式匹配。当P的 template-parameter-list 包含模板参数包(14.5.3)时,模板参数包将匹配零个或多个模板   参数或模板参数包中的   A的 template-parameter-list 与P中的模板参数包具有相同的类型和形式(忽略那些模板   参数是模板参数包。)

可以肯定的是,DEF对于包非常奇怪 - 对于Values的每个专精,ABC必须包含固定数量的参数 - 但根据当前规则,它是&#39;仍然是一个包,所以包的规则适用。

答案 1 :(得分:3)

像巴里先前所说的那样:

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

尝试使用此网站Compiler中的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;

我进行了搜索,找到了这个模板参数列表。

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

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

我在运行代码编译器中测试了一些东西: http://en.cppreference.com/w/cpp/language/parameter_pack 而且我在visual studio 2013中找到了这个Ellipses和Variadic模板: https://msdn.microsoft.com/en-us/library/dn439779.aspx