Reputation: 4255
This works:
class Foo {};
void external_function(Foo&);
void f() {
Foo b;
external_function(b);
}
This does not:
class Foo {};
void external_function(Foo&);
void f() {
external_function(Foo());
}
Clang says:
aac.cc:3:6: note: candidate function not viable: no known conversion from 'Derived' to 'Base &' for 1st argument;
GCC is actually more helpful with:
aac.cc:7:30: error: invalid initialisation of non-const reference of type ‘Base&’ from an rvalue of type ‘Derived’
Herb Sutter (http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/) says a non-const reference can't be used for rvalues, which makes sense in his example, but not in mine, since the object exists for the duration of the external_function() call, doesn't it?
I know how to make it work; Simply create a named object so that it's not an rvalue (as I did above), or use const ref. But I want to know why it's not allowed, since it seems safe to me.
Upvotes: 3
Views: 159
Reputation: 21773
Because the Standard says so, as they believe it is likely to result in bugs (I disagree). There is no technical reason why it is not allowed.
Upvotes: -1
Reputation: 227418
You cannot bind any kind of temporary to a non-const lvalue reference. Inheritance here is just a distraction.
struct Foo{};
void bar(Foo&) {}
void cbar(const Foo&) {}
int main()
{
Foo f;
bar(f); // OK
bar(Foo()); // ERROR
cbar(Foo()); // OK: const reference binds to temporary
}
As to the ultimate "why?", it simply deemed to be error prone to allow modification of an rvalue via an lvalue reference. Quoting from "The C++ Programming Language, Fourth Edition" §7.7.1
References to variables and references to constants are distinguished because introducing a temporary for a variable would have been highly error-prone; an assignment to the variable would become an assignment to the - soon to dissappear - temporary. No such problem exists for references to constants...
Upvotes: 10
Reputation: 9434
The "why" is to avoid difficult to detect bugs. If the argument is not const, that means the function is planning to change it (otherwise just make it const!) Changing a temporary object is not likely to be what you intended and is often a very difficult to figure out bug.
Upvotes: 2