Reference-type conversion operators: asking for trouble?
c++, operator-keyword, operators, reference, type-conversion
Solution
It isn't that an address can't be taken (the compiler could always order it shoved on the stack, which it does with ref-to-const), it's a question of programmers intent. With an interface that takes a A&, it is saying "I will modify what is in this parameter so you can read after the function call". If you pass it a temporary, then the thing it "modified" doesn't exist after the function. This is (probably) a programming error, so it is disallowed. For instance, consider:
void plus_one(int & x) { ++x; }
int main() {
int x = 2;
float f = 10.0;
plus_one(x); plus_one(f);
cout << x << endl << f << endl;
}
This doesn't compile, but if temporaries could bind to a ref-to-non-const, it would compile but have surprising results. In plus_one(f), f would be implicitly converted to an temporary int, plus_one would take the temp and increment it, leaving the underlying float f untouched. When plus_one returned, it would have had no effect. This is almost certainly not what the programmer intended.
The rule does occasionally mess up. A common example (described here), is trying to open a file, print something, and close it. You'd want to be able to do:
ofstream("bar.t") << "flah";
But you can't because operator<< takes a ref-to-non-const. Your options are break it into two lines, or call a method returning a ref-to-non-const:
ofstream("bar.t").flush() << "flah";
Problem
When I compile the following code using `g++` ``` class A {}; void foo(A&) {} int main() { foo(A()); return 0; } ``` I get the following error messages: ``` > g++ test.cpp -o test test.cpp: In function ‘int main()’: test.cpp:10: error: invalid initialization of non-const reference of type ‘A&’ from a temporary of type ‘A’ test.cpp:6: error: in passing argument 1 of ‘void foo(A&)’ ``` After some reflection, these errors make plenty of sense to me. `A()` is just a temporary value, not an assignable location on the stack, so it wouldn't seem to have an address. If it doesn't have an address, then I can't hold a reference to it. Okay, fine. But wait! If I add the following conversion operator to the class `A` ``` class A { public: operator A&() { return *this; } }; ``` then all is well! My question is whether this even remotely safe. What exactly does `this` point to when `A()` is constructed as a temporary value? I am given some confidence by the fact that ``` void foo(const A&) {} ``` can accept temporary values according to `g++` and all other compilers I've used. The `const` keyword can always be cast away, so it would surprise me if there were any actual semantic differences between a `const A&` parameter and an `A&` parameter. So I guess that's another way of asking my question: why is a `const` reference to a temporary value considered safe by the compiler whereas a non-`const` reference is not?