最烦人的解析

Most vexing parse

我在 Cpp Quiz [问题 #38]

看到了代码
#include <iostream>

struct Foo
{
  Foo(int d) : x(d) {}
  int x;
};

int main() 
{ 
  double x = 3.14;

  Foo f( int(x) );

  std::cout << f.x << std::endl;

  return 0;
} 

据说这段代码格式错误,因为 Foo f( int(x) ); 将被视为函数声明而不是类型 Foo 的对象声明。

据我所知,这是一个“最令人头疼的解析”的例子。我的问题是语句 Foo f( int(x) ); 中的语法 int(x) 是什么意思?到目前为止,我只看到像这样的函数声明:

  1. Foo f( int );

  2. Foo f( int x );

Foo f( int x );一样吗?

what does this syntax int(x) in the statement Foo f( int(x) ); mean?

x 两边的括号是多余的,将被忽略。所以 int(x) 和这里的 int x 是一样的,意思是一个名为 x 的参数,类型为 int.

Is it the same as Foo f( int x );?

是的。 Foo f( int(x) );,是一个名为 f、returns Foo 的函数声明,接受一个名为 x 的参数,类型为 int.

这是标准的解释。 [dcl.ambig.res]/1:

(强调我的)

The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in [stmt.ambig] can also occur in the context of a declaration. In that context, the choice is between a function declaration with a redundant set of parentheses around a parameter name and an object declaration with a function-style cast as the initializer. Just as for the ambiguities mentioned in [stmt.ambig], the resolution is to consider any construct that could possibly be a declaration.

Note: A declaration can be explicitly disambiguated by adding parentheses around the argument. The ambiguity can be avoided by use of copy-initialization or list-initialization syntax, or by use of a non-function-style cast.

struct S {
  S(int);
};

void foo(double a) {
  S w(int(a));      // function declaration
  S x(int());       // function declaration
  S y((int(a)));    // object declaration
  S y((int)a);      // object declaration
  S z = int(a);     // object declaration
}

因此,int(x) 将被视为(参数的)声明而不是函数样式转换。

问题是,出于我不知道的原因,在原型中将参数名称括在括号中是有效的。所以

Foo f(int(x));

可以解释为

Foo f(int x);

被认为是

Foo f(int);

然而,真正的问题是 C++ 作者,同样出于我不知道的原因,决定为几乎完全相同的语义(实例初始化)使用两种不同的语法形式是很酷的。

这引入了语法歧义,即 "resolved" 说 "if something can be both a declaration and a definition, then it's a declaration",触发了陷阱。

因此,C++ 解析器必须能够解析任意数量的标记,然后才能确定其中第一个标记的语义含义。

除了编译器编写者之外,这显然不是什么大问题,但这意味着阅读 C++ 代码以理解它的人也必须能够做到同样的事情,而对于我们人类来说,这更难. "most vexing".