是否允许使用多个非类型模板参数包?

时间:2015-07-29 09:54:41

标签: c++ templates c++11 language-lawyer

[temp.param] p11说(在N4527中):

  

(...)函数模板的模板参数包不能跟随另一个模板参数,除非该模板参数可以从函数模板的参数类型列表中推导出来或者具有默认参数

非类型模板参数包的上下文中,不能有默认参数,
那么究竟需要为包推断出什么(只是类型或值)?

即。我想知道标准是否允许这样做(C ++ 11,14或1z):

template<typename T, T... A, T... B>
void foo(T) {}

可以明确指定第一个包的值,但是第二个包是“无法访问的”,如果我没弄错的话,它将永远是空的。

clang ++ - 3.6和g ++ - 5.2似乎接受这些空的无法访问的包(甚至是非非类型包),但VC ++ 14.0拒绝它们并带有错误:

  

错误C3547:模板参数'B'不能使用,因为它遵循模板参数包,不能从'foo'的函数参数中推导出来

1 个答案:

答案 0 :(得分:2)

不,标准不允许这样做。来自[temp.param]:

  

不得遵循功能模板的模板参数包   除非可以从 parameter-type-list 推导出该模板参数,否则使用另一个模板参数   函数模板或具有默认参数(14.8.2)。 [实施例:

template<class T1 = int, class T2> class B;    // error

// U can be neither deduced from the parameter-type-list nor specified
template<class... T, class... U> void f() { }  // error
template<class... T, class U> void g() { }     // error
     

-end example]

在你的情况下,...B无法推断(因为没有什么可以从中推断出来)并且它没有默认参数。

  

那么究竟需要为包推断出什么(只是类型或值)?

例如,如果您的foo是:

template <size_t... A, size_t... B>
void foo(std::index_sequence<B...> );

...A之后是...B,但...B可以推断出来,因此这是允许的。类似地:

template <typename T, T... A, T B = 0>
void foo();

很好,因为B有一个默认参数。