最令人烦恼的解析

时间:2016-08-15 08:01:00

标签: c++ 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 );

  3. Foo f( int x );相同吗?

2 个答案:

答案 0 :(得分:4)

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

Foo f(int(x));

可以解释为

Foo f(int x);

被视为

Foo f(int);

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

这引入了语法模糊性,并且已经解决了#34;通过说&#34;如果某事既可以是宣言又是定义,那么它就是宣言&#34;,触发了陷阱。

因此,C ++解析器必须能够解析任意大量的令牌,然后才能确定第一个令牌的语义含义。

除了编译器编写者之外,这显然不会是一个问题,但是这意味着读取C ++代码以理解它的人也必须能够做同样的事情,而对于我们这些人来说这更难。从那个&#34;最烦恼的&#34;。

答案 1 :(得分:2)

  

语句int(x)中的语法Foo f( int(x) );是什么意思?

x周围的括号是多余的,将被忽略。因此,int(x)与此处的int x相同,表示名为x且参数类型为int的参数。

  

Foo f( int x );相同吗?

是。 Foo f( int(x) );是一个名为f的函数声明,返回Foo,带有一个名为x的参数int

这是标准的解释。 $8.2/1 Ambiguity resolution [dcl.ambig.res]

(强调我的)

  

功能风格之间相似性产生的模糊性   演员和[stmt.ambig]中提到的声明也可能出现在   声明的背景。在这种情况下,选择是在a之间   带有一组冗余括号的函数声明   参数名称和具有函数样式转换为的对象声明   初始化器。就像在提到的含糊不清一样   [stmt.ambig],决议是考虑任何可能的构造   可能是宣言声明。 [注意:声明可以是   通过在参数周围添加括号来明确消除歧义。   通过使用复制初始化或可以避免歧义   列表初始化语法,或使用非函数样式转换。 -   结束语] [例子:

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)将被视为(参数)声明而不是函数样式转换。