合法使用非跟踪功能模板参数包?

use*_*370 5 c++ function-templates default-parameters variadic-templates c++11

在调试某人讨厌的宏生成的代码时,我看到仅MSVC ++对类似于以下函数模板声明的内容不满意:

template <typename ...Vs, typename>
void foo();
Run Code Online (Sandbox Code Playgroud)

很公平。我对为什么GCC和Clang会编译它感到困惑。我foo在上面的声明中添加了的定义,现在GCC也产生了编译错误(Clang仍然存在)。此代码如下:

template <typename ...Vs, typename>
void foo();

template <typename ...Vs, typename = int>
void foo() {  }

int main(int argc, char *argv[])
{
  foo<char,float>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

Clang是对还是错?我注意到,如果删除了声明,则GCC和MSVC ++可以编译。

son*_*yao 5

lang是正确的。如果以下参数具有默认参数,则模板参数包可能会更早出现。

在主类模板中,模板参数包必须是模板参数列表中的最终参数。在功能模板中,模板参数包可能会出现在列表的前面,但前提是可以从函数参数中推导以下所有参数,或使用默认参数:

template<typename... Ts, typename U> struct Invalid; // Error: Ts.. not at the end

template<typename ...Ts, typename U, typename=void>
void valid(U, Ts...);     // OK: can deduce U
// void valid(Ts..., U);  // Can't be used: Ts... is a non-deduced context in this position

valid(1.0, 1, 2, 3);      // OK: deduces U as double, Ts as {int,int,int}
Run Code Online (Sandbox Code Playgroud)

然后给定foo<char,float>();Vs推导为char, float,第二个模板参数为int

根据标准[temp.param] / 13

如果主类模板,主变量模板或别名模板的模板参数是模板参数包,则它应该是最后一个模板参数。除非可以从功能模板的参数类型列表([dcl.fct])推导出该模板参数或具有默认参数([temp。扣除])。

关于gcc和msvc的行为,

如果删除该声明,则GCC和MSVC ++将成功编译。

Gcc和MSVC似乎无法合并默认模板参数默认模板参数出现在声明中,并且应该合并定义。

出现在声明和定义中的默认模板参数与默认函数参数的合并方式相似:

template<typename T1, typename T2 = int> class A;
template<typename T1 = int, typename T2> class A;
// the above is the same as the following:
template<typename T1 = int, typename T2 = int> class A;
Run Code Online (Sandbox Code Playgroud)