其他分享
首页 > 其他分享> > c – 我可以扩展参数包并用它定义参数列表吗?

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.2GCC v7返回错误.
> s.m< 0>();: clang v3.9编译它,GCC v6.2返回错误,GCC v7用ICE停止编译.
> s.m<>();: clang v3.9,GCC v6.2GCC 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