That's not undefined. That's exactly what const_cast
is for. As long as the object itself is non-const
then you can cast it away with const_cast
and do the same things with it as a non-const
pointer.
Do note that const_cast
is usually considered a code smell and might indicate bad design.
As the standard says:
In the body of a non-static
([class.mfct]) member function, the
keyword this
is a prvalue whose value is a pointer to the object for
which the function is called. The type of this in a member function of
a class X
is X*
. If the member function is declared const, the type of
this is const X*
, if the member function is declared volatile
, the
type of this is volatile X*
, and if the member function is declared
const volatile
, the type of this is const volatile X*
.
The type of this
is const X*
in your case even though the object itself is non-const
.
The standard says this about const_cast
:
For two similar types T1
and T2
, a prvalue of type T1
may be
explicitly converted to the type T2
using a const_cast
. The
result of a const_cast
refers to the original entity.
So, casting from const X*
to X*
is also legal.
Lastly, it says (albeit in a note):
[ Note: Depending on the type of the object, a write operation through
the pointer, lvalue or pointer to data member resulting from a
const_cast that casts away a const
-qualifier may produce undefined
behavior ([dcl.type.cv]). — end note ]
And [dcl.type.cv]
tells us:
Any attempt to modify ([expr.ass], [expr.post.incr], [expr.pre.incr])
a const object ([basic.type.qualifier]) during its lifetime
([basic.life]) results in undefined behavior.
Luckily, our this
is pointing to a non-const
object, so casting it and then modifying this object through the new non-const
pointer doesn't trigger undefined behaviour.
Sorry Angew.