Thomas
Thomas

Reputation: 4255

Why can't a temporary be sent as ref args to a function in C++?

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

Answers (3)

Neil Kirk
Neil Kirk

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

juanchopanza
juanchopanza

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

Dale Wilson
Dale Wilson

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

Related Questions