Consider this code,
struct A {};
struct B { B(const A&) {} };
void f(B)
{
cout << \"f()\"<
The problem is that the implicit conversion from a to a B object yields an rvalue. Non-const references can only bind to lvalues.
If B had a default constructor you would get the same behavior if you change the f(a)
call to f(B())
.
--
litb provides a great answer to what is an lvalue: Stack Overflow - often used seldom defined terms: lvalue
GotW #88: A Candidate For the “Most Important const”
Stack Overflow - How come a non-const reference cannot bind to a temporary object?
--
To explain with references to the standard how those function calls fail or succeed would be excessively long. The important thing is how B& b = a;
fails while const B& b = a;
does not fail.
(from draft n1905)
A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:
- [is an lvalue and is either reference compatible or implicitly convertible to an lvalue of a reference compatible type...]
- Otherwise, the reference shall be to a non-volatile const type (i.e., cv1 shall be const).
Here's a case where something is convertible to an lvalue of reference compatible type.