According to the standard (§5.2.11) a const_cast casts away cv-qualifiers (const or volatile).
Here's a simple example. First you declare two functions taking a pointer and a reference:
class Bar { ... };
void foo_ptr(Bar*);
void foo_ref(Bar&);
then you create a reference-to-const:
Bar b;
const Bar& cb = b;
and then you can call either function by using the appropriate const_cast:
foo_ptr(const_cast<Bar*>(&cb));
foo_ref(const_cast<Bar&>(cb));
Here's my question: since const_cast cannot do what the other casts were designed for, isn't it obvious what you're casting to? In other words, why doesn't the language allow me to simply say:
foo_ptr(const_cast<>(&cb));
foo_ref(const_cast<>(cb));
I can think of only the following two reasons:
a) The compiler should stop me when I try to do something crazy, like:
foo_ptr(const_cast<int*>(&cb));
foo_ref(const_cast<int&>(cb));
and by forcing me to explicitly state the type I'm casting to it can then keep me from misbehaving. I find this (hypothetical) explanation weak, since it would be bizarre if the language favored allowing me to write down something wrong only to have the compiler correct me.
b) There is a possible ambiguity if the variable is both const and volatile. In that case the compiler would have no way of telling if I'm trying to cast away the one or the other (or both).
Is that why, or is there another reason?
const_cast
can be used to add or remove const
and volatile
qualifiers. So, if such a syntax were allowed, all of the following would be legitimate target types of const_cast<>(&cb)
:
Bar* (1)
const Bar* (2)
volatile Bar* (3)
const volatile Bar* (4)
You intend (1). (2) is usually silly, but it is conceivable that it might occur somewhere, perhaps in some template code. (3) and (4) are indeed the problems: you can remove the const
qualification and add the volatile
qualification all with a single cast.
You could replace the existing const_cast
with a pair of casts, const_cast
and volatile_cast
, and prohibit case (2); then you could use either of them without the target type. However, then it's more difficult to know the type of the cast expression. To know whether a cast expression adds or removes qualification, you have to know what the type of the source expression is.
There's no reason you couldn't use a function template to get what you want:
template <typename T>
T* remove_const(const T* p) {
return const_cast<T*>(p);
}
You could easily write similar functions for remove_volatile
and for add_const
and add_volatile
, which are both implicit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With