功能模板参数包,后跟模板参数和专门化

时间:2019-06-29 17:06:12

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

在功能模板的定义中使用的模板参数包是否可以在定义中仅赋予该参数其所需的默认值之后,跟随另一个模板参数;而不是宣言?考虑以下示例:

template <typename ...Ts, typename T>
auto sz(Ts...);

template <typename ...Ts, typename T = int>
auto sz(Ts...) { return sizeof...(Ts); }

我发现GCC和Clang在这一点上存在分歧(GCC给出了编译错误)。

1 个答案:

答案 0 :(得分:4)

-编辑-在最初的误会之后已得到纠正。

我想g ++是正确的,而clang ++是错误的。

根据C ++ 17标准17.1.11

  

模板参数   一组功能模板之后不应再有另一个模板参数,除非该模板   参数可以从功能模板的parameter-type-list(11.3.5)推导出,也可以使用默认值   论点(17.8.2)。

因此,可变参数包装后,应接受具有默认值的模板参数。

问题是:我们只能在函数声明中或在函数定义中(与函数声明不同时)设置模板默认值吗?

实际上,您可以使用

来简化您的问题
template <typename>
void foo ();

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

int main ()
 {
   foo();
 }

被clang ++接受,被g ++拒绝。

对我来说这还不是很清楚,但是我在17.1.9中读过

  

默认   模板参数   可以在模板声明中指定。   默认值   模板参数   不得在   模板参数列表   的定义   出现在成员班级之外的班级模板的成员。默认值   模板参数   应   不能在好友类模板声明中指定。如果朋友功能模板声明指定了   默认   模板参数   ,该声明应为定义,并且是该声明的唯一声明   翻译单元中的功能模板

此片段明确指出“可以在模板声明中指定默认模板参数”。不属于“定义”。

排除“不应在出现在成员类之外的类模板的成员的定义的template-parameter-list中指定默认模板参数”,因此我最初得出的结论是,模板通用函数可以在“定义”中指定默认模板参数,但这部分是关于“类模板”的,因此模板参数是关于类的,而不是关于成员的。

正如10.1.10中sigma所指出的(谢谢!),我们可以阅读

  

默认设置   模板参数   可以通过合并来自   模板的所有先前声明都以默认函数参数相同的方式

同样:“声明”而不是“定义”。

所以我认为clang ++是错误的,而g ++是正确的。