The reason why both fail to compile is that temporaries cannot be bound to non-const references.
In the first case, the expression abc()
constructs a temporary abc
object. Trying to pass it to fun()
tries to bind the temporary to a non-const reference; this is disallowed.
The second case is effectively the same thing: the compiler tries to use 5
to construct an int
temporary, but then fails to bind it to the non-const reference.
int const & a = 5; // allowed
int & b = 5; // disallowed
This was an intentional design decision, intended to prevent what would otherwise be very easy mistakes to make. Let's pretend this rule doesn't exist:
void add_one(double & i) {
i += 1;
}
void something() {
int x = 5;
add_one(x);
std::cout << x;
}
Wait... why is x
5 instead of 6!? Because x
was used to construct a double
temporary, which bound to the reference argument. add_one()
added 1 to the temporary. Then the temporary is destroyed when control returns to something()
and the value of x
was never changed.
But, since temporaries cannot bind to non-const references, the add_one(x)
line will instead fail to compile. This saves the programmer from having to figure out that an invisible temporary was implicitly created and destroyed on that one line of code.