从[temp.variadic](工作草案),在我看来,在定义另一个模板类或函数的参数列表时,可以扩展参数包。
考虑以下课程:
S
目的是捕获用于专门化模板类m
的类型,并使用它们为成员方法T
定义非类型参数的参数列表(当然,s.m<0, 'c'>()
仅限于几种类型,但这不是问题的论据。)
这是合法代码吗?我可以按照我使用它的方式使用参数包,还是我误解了标准(非常确定确实是这样)?
为了在问题中添加更多细节,以下是主要编译器的一些实验的一些结果:
s.m<0>();
:clang v3.9对其进行编译,GCC v6.2和GCC v7会返回错误。
s.m<>();
:clang v3.9编译它,GCC v6.2返回错误,GCC v7停止使用ICE进行编译。
{{1}}:clang v3.9,GCC v6.2和GCC v7编译时没有错误。
至少,编译器似乎和我一样困惑。
答案 0 :(得分:2)
模板S
的定义以及S<int, char>
的实例化有效。
参见[temp.param] / 15:“模板参数包是参数声明,其类型包含一个或多个未展开的参数包,是包扩展。”
这意味着template<T ...I>
可能意味着两种不同的东西之一:如果T
是非包装类型,那么它声明一个普通的参数包,接受任意数量的T
s 。但是,如果T
包含未扩展的参数包,则在实例化外部模板时,参数声明将扩展为一系列参数。
您对[{1}}的第一次通话有效,但您对m
的第二次和第三次通话格式不正确
m
的实例化如下:
S<int, char>
(其中template<>
struct S<int, char> {
template<int I$0, char I$1>
void m() {}
};
和I$0
是包I$1
)的第一个和第二个切片。
因此(因为调用I
)无法推断I$0
和I$1
,m
有效但s.m<0,'c'>()
和s.m<0>()
是不正确的。