C++ 最烦人的解析是使用限定id,还是不使用?

C++ 最烦人的解析是使用限定id,还是不使用?,c++,most-vexing-parse,C++,Most Vexing Parse,考虑: struct Foo { enum { bar }; explicit Foo(int){} }; struct Baz { explicit Baz(Foo){} }; Baz b(Foo(Foo::bar)); // #1 即使Foo::bar是一个限定的id并且不可能是一个有效的参数名,第#1行是最麻烦的解析吗;哪个编译器是正确的?Clang是正确的 有些令人惊讶的是,参数声明语法同时允许限定ID和非限定ID,因为它接受所有声明符: 声明器的语法允许限定I

考虑:

struct Foo {
     enum { bar };
     explicit Foo(int){}
};

struct Baz { explicit Baz(Foo){} };

Baz b(Foo(Foo::bar)); // #1
即使
Foo::bar
是一个限定的id并且不可能是一个有效的参数名,第#1行是最麻烦的解析吗;哪个编译器是正确的?

Clang是正确的

有些令人惊讶的是,参数声明语法同时允许限定ID和非限定ID,因为它接受所有声明符:

声明器的语法允许限定ID和非限定ID。不管好坏,“函数参数名没有限定id”规则都是一种语义规则,尽管可以很容易地为直接排除限定id的参数声明编写语法

就像中的情况一样,消歧规则是纯语法的,而且

Baz b(Foo(Foo::bar));
可以语法上解析为函数声明,它就是这样解析的,即使在这种情况下消除歧义会导致无法编译的结果


另请参见。

我想说这看起来很熟悉;-)因此,谁是正确的
gcc
clang
,这应该是显而易见的,但最好是更加明确。@ShafikYaghmour关于同一主题的变体,可以肯定:)这个案例确实让我吃惊,我通常很擅长发现MVP……这个答案是基于语言语法(语言语法)的假设仅通过正式语法(如附录A所示)进行描述。标准文本中额外列出的所有其他限制/要求都不是语法性的(正如答案所说,它们是语义性的)。这可能是真的,但在我看来,这是一种描述语言语法的效率极低的方法。仅用形式化语法来描述整个语法通常是非常低效的。能够将语法规则分为语法中的语法规则和随语法一起用纯文本描述的语法规则,使得规范更加灵活、紧凑和可读。我希望语言标准的作者可以自由地从形式语法中“提取”一些规则,并用文本描述代替它们,反之亦然。语言的语法可以用形式语法和伴随的语法规则在纯文本中的组合来描述。这就是我如何看待禁止使用限定名作为参数名的问题。这是一个纯粹的语法规则,被认为更适合于文本描述(以避免语法过于复杂)。(是的,我知道,将这个要求嵌入到正式语法中可能不太困难,但无论如何……)我之所以认为GCC的行为是“更合乎逻辑的”,在这种情况下:GCC理解(假设正确)“考虑任何可能构成声明的结构”。该要求还包括检查“无限定名称作为参数名称”规则。
Baz b(Foo(Foo::bar));