32
votes

On Wikipedia I found this:

A a( A() );

[This] could be disambiguated either as

  1. a variable definition of class [A], taking an anonymous instance of class [A] or
  1. a function declaration for a function which returns an object of type [A] and takes a single (unnamed) argument which is a function returning type [A] (and taking no input).

Most programmers expect the first, but the C++ standard requires it to be interpreted as the second.

But why? If the majority of the C++ community expects the former behavior, why not make it the standard? Besides, the above syntax is consistent if you don't take into account the parsing ambiguity.

Can someone please enlighten me? Why does the standard make this a requirement?

5
Where is there a function pointer?Lightness Races in Orbit
Read the error message -- ideone.com/12sT80#view_edit_box Aren't function pointers of type T (*)()?template boy
@templateboy: The message is misleading: in that context a has essentially decayed to a function pointer for use in the expression a.f, but the declaration itself of a has nothing to do with function pointers.Lightness Races in Orbit
@downvoter May I have an explanation?template boy

5 Answers

19
votes

Let's say MVP didn't exist.

How would you declare a function?

A foo();

would be a variable definition, not a method declaration. Would you introduce a new keyword? Would you have a more awkward syntax for a function declaration? Or would you rather have

A foo;

define a variable and

A foo();

declare a function?

Your slightly more complicated example is just for consistency with this basic one. It's easier to say "everything that can be interpreted as a declaration, will be interpreted as a declaration" rather than "everything that can be interpreted as a declaration, will be interpreted as a declaration, unless it's a single variable definition, in which case it's a variable definition".

This probably isn't the motivation behind it though, but a reason it's a good thing.

15
votes

For C++, it's pretty simple: because the rule was made that way in C.

In C, the ambiguity only arises with a typedef and some fairly obscure code. Almost nobody ever triggers it by accident -- in fact, it probably qualifies as rare except in code designed specifically to demonstrate the possibility. For better or worse, however, the mere possibility of the ambiguity meant somebody had to resolve it -- and if memory serves, it was resolved by none other than Dennis Ritchie, who decreed that anything that could be interpreted as a declaration would be a declaration, even if there was also an ambiguous interpretation as a definition.

C++ added the ability to use parentheses for initialization as well as function calls as grouping, and this moved the ambiguity from obscure to common. Changing it, however, would have required breaking the rule as it came from C. Resolving this particular ambiguity as most would expect, without creating half a dozen more that were even more surprising would probably have been fairly non-trivial as well, unless you were willing to throw away compatibility with C entirely.

6
votes

It's a side-effect of the grammar being defined recursively.

It was not designed intentionally like that. It was discovered and documented as the most vexing parse.

5
votes

This is just a guess, but it may be due to the fact that with the given approach you can get both behaviors:

A a( A() ); // this is a function declaration
A a( (A()) ); // this is a variable definition

If you were to change its behavior to be a variable definition, then function declarations would be considerably more complex.

typedef A subfunction_type();

A a( A() ); // this would be a variable declaration
A a( subfunction_type ); // this would be a function declaration??
1
votes

No particular reason, other than [possibly] the case that K-ballo identifies.

It's just legacy. There was already the int x; construction form so it never seemed like a reach to require T x; when no ctor args are in play.

In hindsight I'd imagine that if the language were designed from scratch today, then the MVP wouldn't exist... along with a ton of other C++ oddities.

Recall that C++ evolved over decades and, even now, is designed only by committee (see also: camel).