5

Why does the compiler interpret this line as a function definition and not as a variable definition:

Y y(X());

in the following code:

#include <iostream>

struct X {
  X() { std::cout << "X"; }
};

struct Y {
  Y(const X &x) { std::cout << "Y"; }
  void f() { std::cout << "f"; }
};

int main() {
  Y y(X());
  y.f();
}

VS2010 gives the following error on line "y.f();"

left of '.f' must have class/struct/union

Which part of the standard describes this behavior? The answer to the following question doesn't give details about it: Most vexing parse

Community
  • 1
  • 1
Laura Maftei
  • 1,863
  • 1
  • 15
  • 25
  • 1
    This is not a compiler bug by the way. It's the most vexing parse problem, cunningly disguised. – Bathsheba Oct 16 '14 at 08:37
  • 1
    Voted to reopen based on the edit - a quote from the standard would actually be useful. 6.8 talks about disamiguating expression statements vs. declarations, but the most vexing parse is actually an ambiguity between two declarations. – Angew is no longer proud of SO Oct 16 '14 at 08:59

2 Answers2

6

Consider this :

float foo( int () )

This declares a function foo ( accepting a function returning int ) returning float.

Now read

Y y(X());

as y as function (accepting a function returning X) returning Y

The problem arises due to C++ most vexing parse

Can be solved with :

 Y y{ X() }; // requires C++11

or

Y y( ( X() ) );
  // ^     ^ notice parenthesis 

Update based on edit:

A quote from the standard :

§ 8.2 Ambiguity resolution [dcl.ambig.res]

1 - The ambiguity arising from the similarity between a function-style cast and a declaration mentioned in 6.8 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 6.8, the resolution is to consider any construct that could possibly be a declaration a declaration. [Note: a declaration can be explicitly disambiguated by a nonfunction-style cast, by a = to indicate initialization or by removing the redundant parentheses around the parameter name. ]

[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 z = int(a); // object declaration
}
—end example]

Similarly other examples following this.

Community
  • 1
  • 1
P0W
  • 46,614
  • 9
  • 72
  • 119
5

Most vexing parse problem. Y y(X()) is actually function declaration with name y, that returns Y and receives argument of type function, that returns X and receives nothing.

It's solved in C++11 with usage of {} for construct object.

ForEveR
  • 55,233
  • 2
  • 119
  • 133