函数类型别名声明中是否允许嵌套括号?

Igo*_*r G 7 c++ language-lawyer compiler-specific c++17 alias-declaration

以下代码可以使用 gcc-13 和 clang-16 编译,但 MSVC 报告多个错误

using foo_type = void ((((int, const char*))));   // (1)
// Compiler messages for line (1):
//    clang-16: ok.
//    gcc-13:   ok.
//    MSVC-v19: error C2062: type 'int' unexpected.


foo_type foo;

int main()
{
    foo(5, "Hello");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

问题是:谁是对的?标准是否允许alias-declaration函数类型在参数列表周围有多个嵌套括号,就像上面的示例中所尝试的那样?

use*_*522 5

是的,该语法是允许的,并且不特定于别名声明。它适用于所有声明符。

通常,您可以根据需要在声明符周围放置任意数量的括号。对于像这里这样的抽象声明符,除了声明符 id之外没有任何变化(即名称)被省略之外,没有任何变化。具有尾随返回类型的声明符是一个例外。

例如,以下内容也是有效的:

void (((foo(int, const char*))));

int main()
{
    foo(5, "Hello");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

出于同样的原因,您还可以在函数参数中的* 抽象声明符周围添加括号:

using foo_type = void ((((int, const char(((*)))))));
Run Code Online (Sandbox Code Playgroud)

特别是对于标签,请参阅非抽象情况下的语法产生式和抽象情况下的( ptr-declarator )语法产生式。noptr-declarator( ptr-abstract-declarator )noptr-abstract-declarator

  • @TobySpeight _alias-declaration_ → `using` _identifier_ `=` _defining-type-id_ ;_定义类型 id_ → _定义类型说明符-seq_ _抽象声明符_ ;_定义类型说明符-seq_ → … → `void` ; _abstract-declarator_ → _ptr-abstract-declarator_ → _noptr-abstract-declarator_ → `(` _ptr-abstract-declarator_ `)` → `(` _noptr-abstract-declarator_ `)` → `(` _参数和限定符_ `) ` (3认同)
  • (不)有趣的是,GCC 接受 `using foo_type = auto ((((int, const char*) -> void)));` (2认同)