5

This code causes compilation error (most vexing parse)

#include <iostream>

class A {
        int a;
public:
        A(int x) :a(x) {}
};

class B {
public:
        B(const A& obj) { std::cout << "B\n";}
        void foo() {std::cout << "foo\n";}
};

int main()
{
        int test = 20;
        B var(A(test));      //most vexing parse
        var.foo();
        return 0;
}

But if I pass 20 instead of test (A(20) instead of A(test)), there is no compilation error.

#include <iostream>

class A {
        int a;
public:
        A(int x) :a(x) {}
};

class B {
public:
        B(const A& obj) { std::cout << "B\n";}
        void foo() {std::cout << "foo\n";}
};

int main()
{
        int test = 20;
        //B var(A(test));
        B var(A(20));            //ok works fine
        var.foo();
        return 0;
}

Why is this not considered as most vexing parse? What is the difference between these two code versions?

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
bornfree
  • 2,308
  • 1
  • 23
  • 33
  • 5
    This is basically the example [on Wikipedia](https://en.wikipedia.org/wiki/Most_vexing_parse#Example_with_functions). The second case is not vexing because `20` cannot be a variabl ename. – Raymond Chen Feb 21 '19 at 15:50

2 Answers2

11

A variable can be defined like

type(name)

Because of that

B var(A(test)); 

declares a function named var that returns a B and takes an A named test. In

B var(A(20));

if you tried to do the same thing, the A parameter would be called 20, which is not a valid variable name. Since it cannot be the name of a variable we know it is a value and instead we are constructing a variable named var of type B with the value of A(20).

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
5

The most-vexing-parse issue is a problem of grammar, not semantics. Grammatically, A(test) boils down to identifier : OPEN_PAREN : identifier : CLOSE_PAREN. In context, this is ambiguous because the second identifier could be a variable name or a typename. The compiler has to pick a way of interpreting this sequence of tokens, and neither one is incorrect.

By contrast, A(20) boils down to identifier : OPEN_PAREN : integer_literal : CLOSE_PAREN. An integer literal cannot be interpreted as an identifier, so there is no way to interpret it as a typename. It must therefore be parsed as an expression which initializes an object of type A.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982