I would like to check my understanding and conclusions on this matter.
On IRC, it was asked:
Is it acceptable to
const_cast
aconst
reference that's bound to a temporary object?
Translating: he has a ref-to-const bound to a temporary, and he wants to cast away its const
-ness to modify it.
My response was that I'd asked a similar question previously, where the consensus seemed to be that temporaries themselves are not inherently const
, and thus that you can cast off the const
-ness of a reference you have to them, and modify them through the result. And, as long as that original ref-to-const
still exists, this won't affect the temporary's lifetime.
That is:
int main()
{
const int& x = int(3);
int& y = const_cast<int&>(x);
y = 4;
cout << x;
}
// Output: 4
// ^ Legal and safe
Am I right?
(Of course, whether or not such code is actually advisable is another matter entirely!)
No.
First, as far as I can tell, whether it is a literal or not is irrelevant. Rvalues of non-class types always have non-cv qualified types (§3.10/9), however, in §8.5.3 (initialization of a reference), we have:
(All of the preceding points concern either lvalues or class types.)
In our case, we have:
So cv1 T1 is
int const
, and the temporary object we create has typeint const
. This is a top level const (on the object), so any attempt to modify it is undefined behavior.At least, that's my interpretation. I wish the standard were a bit clearer about this.
The answer depends on how the temporary is created and how the reference is initialized.
If you explicitly created the temporary yourself as an object of non-const type and the situation guarantees that the const-reference is attached specifically to the temporary you created, then you can safely cast away the constness of the reference and modify the object.
On the other hand, if the temporary was implicitly created for you by the compiler, then the temporary itself will be const. In that case modifying that temporary leads to UB.
Unfortunately, the C++ language standard by itself does not seem to seem to guarantee any situations where the first initialization approach is necessarily taken. In any context the compiler is allowed to introduce an extra temporary copy of your original temporary. The new temporary will be const (as stated above) and therefore non-modifiable. Whether this happens or not is implementation-defined, as stated in 8.5.3/5.
So, in general case the answer is no, while an implementation-specific answer might be different.