c++c++11most-vexing-parse

What is the difference between these two versions of code?


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?


Solution

  • 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).