views:

95

answers:

4

Consider the following code.
Here, A a(B()) compiles even though the constructor is A(B& b); But print(B()) does not work. But print is also declared as print(B& b); Why this inconsistency?

#include <iostream>
using namespace std;

class B{
    public:
            char b;
};

class A {
    public:
            B b;
            A(B& b);
            A() { }
};

A::A(B& b) {
    this->b = b;
}

void print(B& b) { }

int main(){
    print(B());
    A a(B());
}
+1  A: 

You should not be passing a non-constant reference to a temporary, so the print statement should not compile. If you modify that reference in print to const, it will work.

Eli Bendersky
+3  A: 

This:

A a(B());

isn't doing what you think. It is actually parsed as a function declaration. This is commonly referred to as the "most vexing parse" in C++ (there are many posts here about it, if you search for that phrase).

James McNellis
+6  A: 

It compiles because it's not creating an instance of A. It's declaring a function named a that returns an A and receives one unnamed parameter of type pointer-to-function-returning-B. Since it's just a declaration, it compiles. If you're referred to a elsewhere in the code, you'd have seen additional problems. For why that's a function declaration instead of an object definition, the term to look up is most vexing parse.

Rob Kennedy
This is so bloody bad! Does C++ even allow you do Declare a function INSIDE another funcion? Why does C++ allow that? Why would anyone need such a facility?
ajay
Yes, C++ does allow it. Obviously, since you just did. It's a declaration inside a function because it's a declaration everywhere else. Put that line inside a class declaration, and it's a member-function declaration. Put it outside anything else, and it's a function declaration. It's a function declaration no matter where you put it.
Rob Kennedy
I think it is perfectly possible to modify the compiler to add the condition that if such a thing happened inside the definition of a function, it is not a function declaration, but a object declaration. I am surprised why they decided not to fix it.
ajay
@ajay: It's allowing it for backward compatibility: C allowed it. Nobody is happy about it, but not allowing it might break millions of lines of code.
sbi
Oh! I see. A necessary evil.
ajay
+1  A: 

Where you are trying to call the constructor you are actually declaring a function:

A a(B());

This declares a as a function returning A and taking as parameter a function pointer returning B and taking no parameters.

Actually trying to call the constructor results in an error, as expected:

A a = A(B());

tst.cpp:32: error: no matching function for call to ‘A::A(B)’

sth