最烦人的解析
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)
是什么意思?到目前为止,我只看到像这样的函数声明:
Foo f( int );
和
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".
我在 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)
是什么意思?到目前为止,我只看到像这样的函数声明:
Foo f( int );
和Foo f( int x );
和Foo f( int x );
一样吗?
what does this syntax
int(x)
in the statementFoo 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".