可变参数模板在 gcc 中有效,但在 clang 中无效

Ale*_*lex 15 c++ templates variadic-templates

我正在使用此处列出的书籍学习 C++ 。我特别读到了有关可变参数模板的内容。现在,为了进一步阐明我的概念,我还编写了简单的示例,并尝试使用调试器和 cout 语句自己理解它们。

下面给出了一个用 gcc 编译但被 clang 拒绝的程序。演示

template<typename T, typename... V> 
struct C 
{
    T v(V()...);;
};
int main()
{
    
    C<int> c; //works with gcc but rejected in clang 
    C<int, double, int, int> c2; //same here: works with gcc but rejected in clang
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是哪个编译器就在这里(如果有的话)?

这是 clang 给出的错误:

<source>:6:12: error: '...' must be innermost component of anonymous pack declaration
    T v(V()...);;
           ^~~
          ...
1 error generated.
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)

Hol*_*Cat 10

这是一个海湾合作委员会错误。正确的语法是T v(V...());,Clang 接受而 GCC 拒绝(错误)。

在函数参数列表中,...展开包的 必须位于参数名称之前,或者位于名称原本所在的位置。这种情况在类似的情况下更常见V &&... v

相关语法为:函数定义->声明符->参数和限定符-> ... ->参数声明->抽象声明符(“抽象”=无参数名称)。

[dcl.fct]/26表示如果函数参数列表中存在歧义,无论...是包扩展还是 C 样式可变参数,它都会解析为包扩展。但在这种情况下,没有歧义,V()...使包不展开(这应该是编译错误)并且...应该是 C 风格的可变参数。

  • 这似乎是正确的。_abstract-declarator_ 的语法对于 pack 变体和非 pack 变体具有不同的术语,并且只有非 pack 变体具有将 (ptr-) 声明符括起来的术语。 (2认同)

use*_*570 5

GCC 在接受程序时是错误的,因为函数参数包是...在函数参数名称之前(或代替)使用省略号 ( ) 引入的。

这意味着在您的示例中,声明具有函数指针类型参数的函数的正确方法是T v(V...());。但请注意,gcc 拒绝此修改后的代码。演示

这是 gcc 错误报告:

GCC 接受涉及带有包扩展的函数声明的无效程序

笔记

有趣的是,gcc 拒绝T v(V...())但接受T v(V...b())演示

template<typename T, typename... V> 
struct C 
{
//-------vvv---------->this is the correct way which gcc rejects 
    T v(V...());
//-------vvv---------->but gcc accepts this when we name the parameter
    T v(V...b());
};
Run Code Online (Sandbox Code Playgroud)

  • 语法不应该是“T v(V...());”吗?类似于“V &amp;&amp;... v”。Clang 接受这一点,但 GCC 不接受。对我来说看起来更像是一个 GCC bug。 (3认同)