问题
This question already has an answer here:
- A confusing detail about the Most Vexing Parse 4 answers
I saw a code here at Cpp Quiz [Question #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;
}
It is said there that this code is ill formed because Foo f( int(x) );
will be treated as a function declaration rather than an object declaration of type Foo
. As far as I know, this is an instance of most vexing parse. My question is what is this syntax int(x) in statement Foo f( int(x) );
means? So far I only saw function declarations like:
Foo f( int );
andFoo f( int x );
Is it same as Foo f( int x );
?
回答1:
what is this syntax
int(x)
in statementFoo f( int(x) );
means?
The parentheses around x
are superfluous and will be ignored. So int(x)
is same as int x
here, means a parameter named x
with type int
.
Is it same as
Foo f( int x );
?
Yes. Foo f( int(x) );
, is a function declaration which is named f
, returns Foo
, takes one parameter named x
with type int
.
Here's the explanation from the standard. $8.2/1 Ambiguity resolution [dcl.ambig.res]:
(emphasis mine)
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 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. — end note ] [ Example:
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 }
— end example ]
So, int(x)
will be considered as a declaration (of parameter) rather than a function style cast.
回答2:
The problem is that, for reasons unknown to me, it's valid to wrap parameter names into parenthesis in prototypes. So
Foo f(int(x));
can be interpreted as
Foo f(int x);
that is considered as
Foo f(int);
The real issue is however that C++ authors, also for reasons unknown to me, decided that it was cool to have two different syntax forms for the almost very same semantic (instance initialization).
This introduces an syntax ambiguity that is "resolved" by saying that "if something can be both a declaration and a definition, then it's a declaration", triggering the trap.
Because of that a C++ parser therefore must be able to parse an arbitrarily large number of tokens before being able to decide what is the semantic meaning of the very first of them.
This apparently wouldn't have been too much of an issue except for compiler writers, but however it means that also who reads C++ code to understand it must be able to do the same, and for we humans this is harder. From that the "most vexing".
来源:https://stackoverflow.com/questions/38951362/most-vexing-parse