Rahul said:
I think, as the temp object is that of an in-built type, it is fine.
But had it been that of a custom type, the temp object would have been
an constant object...
It's the other way around. It could work with a class type.
To provide lost context, we consider code like this:
const double& ref = 100; // *
double& d = const_cast<double&>(ref);
d = 1.1;
Clearly, line (*) is the important line. Its meaning is governed by
[8.3.5/5], which is too long to quote in full, so I cut out irrelevant
parts:
A reference to type ?cv1 T1? is initialized by an expression of type
?cv2 T2? as follows:
? If the initializer expression
? is an lvalue ...
? has a class type ... and can be implicitly converted to an lvalue ...
? Otherwise, the reference shall be to a non-volatile const type ...
? If the initializer expression is an rvalue, with T2 a class type, ...
? Otherwise, a temporary of type ?cv1 T1? is created and initialized
from the initializer expression using the rules for a non-reference
copy initialization (8.5). The reference is then bound to the
temporary. If T1 is reference-related to T2, cv1 must be the same
cv-qualification as, or greater cvqualification than, cv2; otherwise,
the program is ill-formed.
In line (*), the initializer is an rvalue not convertible to an lvalue. That
puts us in the first "Otherwise" item. Also, it is not of class type, which
puts us in the "Otherwise" subitem. The provision then states that the
const reference is bound to a temporary of type cv1 T1 (in our case that is
a temporary of type const double). Modifying that temporary under a
different handle is undefined behavior.
Now consider a class type ClassType:
const ClassType & ref = some_expression_of_ClassType;
ClassType & handle = const_cast< ClassType& >( ref );
handle = some_other_expression;
We then have the following verions of [8.5.3/5]:
A reference to type ?cv1 T1? is initialized by an expression of type
?cv2 T2? as follows:
? If the initializer expression
? is an lvalue ...
? has a class type ... and can be implicitly converted to an lvalue ...
? Otherwise, the reference shall be to a non-volatile const type ...
? If the initializer expression is an rvalue, with T2 a class type,
and ?cv1 T1? is reference-compatible with ?cv2 T2,? the reference is
bound in one of the following ways (the choice is
implementation-defined):
? The reference is bound to the object represented by the rvalue (see
3.10) or to a sub-object within that object.
? A temporary of type ?cv1 T2? [sic] is created, and a constructor is
called to copy the entire rvalue object into the temporary. The
reference is bound to the temporary or to a sub-object
within the temporary.
...
...
In this case, depending on the choice of the implementation, the reference
is either bound to a temporary of type ClassType or of type const ClassType
(if the implementation chose the second alternative). Therefore, it is
implementation-defined whether the code has undefined behavior for class
types. (I have a vague recollection that the second alternative is slanted
for elimination in the next version of the standard. In that case, the code
would have well-defined behavior for class types and undefined behavior for
built-in types.)
Best
Kai-Uwe Bux