c – 我可以扩展参数包并用它定义参数列表吗?
作者:互联网
从[temp.variadic](工作草案)开始,在我看来,可以在定义另一个模板类或函数的参数列表时扩展参数包.
考虑以下课程:
template<typename... T>
struct S {
template<T... I>
void m() {}
};
int main() {
S<int, char> s;
// ...
}
目的是捕获用于专门化模板类S的类型,并使用它们为成员方法m定义非类型参数的参数列表(当然,T仅限于几种类型,但这不是问题的论点).
这是合法代码吗?我可以按照我使用的方式使用参数包吗?或者我是否误解了标准(确实确实如此)?
为了在问题中添加更多细节,以下是主要编译器的一些实验的一些结果:
> s.m< 0,'c'>():clang v3.9编译它,GCC v6.2和GCC v7返回错误.
> s.m< 0>();: clang v3.9编译它,GCC v6.2返回错误,GCC v7用ICE停止编译.
> s.m<>();: clang v3.9,GCC v6.2和GCC v7编译它没有错误.
至少,编译器似乎和我一样困惑.
解决方法:
模板S的定义和S< int,char>的实例化是有效的.
参见[temp.param] / 15:“模板参数包是一个参数声明,其类型包含一个或多个未展开的参数包,是包扩展.”
这意味着模板< T ... I>可以表示两种不同的东西之一:如果T是非包装类型,则它声明一个正常的参数包,接受任意数量的Ts.但是,如果T包含未扩展的参数包,则在实例化外部模板时,参数声明将扩展为一系列参数.
你第一次打电话给m是有效的,但你对m的第二次和第三次打电话是不正确的
S< int,char>的实例化看起来像这样:
template<>
struct S<int, char> {
template<int I$0, char I$1>
void m() {}
};
(其中我0美元和1美元是我的第一和第二片).
因此(因为对于m的调用都不能推断出I $0和I $1),s.m< 0,'c'>()是有效的但是s.m< 0>()和s.m<> ()是不正确的.
标签:c,language-lawyer,variadic-templates,clang,gcc 来源: https://codeday.me/bug/20191001/1839332.html