Author Topic: Most Vexing Parse  (Read 2750 times)

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4955
Most Vexing Parse
« on: October 12, 2018, 10:52:19 PM »
I was looking at some C++ code, and one line stood out to me for a moment while I pondered how to parse it. Was it a forward declaration for a function, or a global object being constructed.

Turns out there is an ambiguity in the C++ grammar. The problem has become know as the Most Vexing Parse.

Consider the following code (which I don't think actually qualifies as the Most Vexing Parse, but is related):
Code: cpp [Select]

SomeClassType maybeAnObjectMaybeAFunctionName();


Is this declaring a global object, or is this a forward declaration for a function which takes no arguments and returns an object of type SomeClassType? Many programmers might look at that an assume it's an object declaration, but it's actually a forward declare.

If you want an object declaration, omit the ():
Code: cpp [Select]

SomeClassType maybeAnObjectMaybeAFunctionName;




The Most Vexing Parse comes in when there are arguments. In which case, how it is interpreted depends on whether the arguments are expressions or types.
Code: cpp [Select]

SomeClassType maybeAnObjectMaybeAFunctionName(ObjectName());


Here ObjectName is a type. In this case, you might view this as calling the constructor for that type, in which case ObjectName() would represent an expression. However, the compiler sees this as a function signature, where ObjectName() represents an anonymous function which takes no parameters, and returns a value of type ObjectName. Given that interpretation, now SomeClassType maybeAnObjectMaybeAFunctionName(ObjectName()); is also interpreted as a function signature. It is a function, which takes a pointer to a function as argument, where the argument function takes no parameters and returns a value of type ObjectName, and the outer function returns an object of type SomeClassType. So you have a forward declaration for a function, rather than declaring and initializing an object. This surprises a lot of people, and isn't usually what they intended, hence the name the Most Vexing Parse.

You can resolve the ambiguity by adding extra parenthesis.
Code: cpp [Select]

SomeClassType maybeAnObjectMaybeAFunctionName((ObjectName()));


As per the grammar, type names can't have arbitrary parenthesis around them, however that's not a problem for expressions, hence (ObjectName()) is interpreted unambiguously as an expression. Given that it's an expression, and not a type, the only possible interpretation for the argument list is then as a method call. Hence you end up defining and initializing a variable.

As a side note, an empty set of parenthesis () is not an expression. There needs to be something inside for it to be an expression. Hence, the rule is add extra parenthesis when initializing an object with arguments, and omit the parenthesis when there are no arguments, and you'll get a variable declaration rather than a forward declaration for a function.

This is another way to avoid the ambiguity. Use Uniform Initialization Syntax:
Code: cpp [Select]

SomeClassType maybeAnObjectMaybeAFunctionName{ObjectName{}};


The braces {} can not be interpreted as a parameter list for a function type, and so it is unambiguously constructing and initializing a variable.


Small footnote: This ambiguity relates to using a class name as the constructor name. Hence a single identifier can be interpreted as either a type name, or a call to a function (the constructor for that type). The ambiguity is resolved in favor of the type name.
« Last Edit: October 12, 2018, 10:57:04 PM by Hooman »

Offline lordpalandus

  • Banned
  • Hero Member
  • *****
  • Posts: 825
Re: Most Vexing Parse
« Reply #1 on: October 13, 2018, 01:53:36 PM »
In any situation dealing with grammar, be it code grammar or language grammar, to avoid ambiguity you should explicitly state what it is you are doing.

If you aren't willing to do that, then said programmer should be led outside with a double barrel shotgun, and be promoted to manager!
Currently working on Cataclysm of Chaos, Remade.
Link to OPU page = http://forum.outpost2.net/index.php/topic,6073.0.html