const_cast removes or adds the const and volitale qualifies to an object.
Your example strike86 isn't a good example of how it can be used because you are using string literal constant. Here is something that will compile.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
class MyClass
{
public:
void Print() //notice this is non-const...
{
std::cout << "Inside Print" << std::endl;
}
};
//void SomeFunction(const &MyClass obj)
//{
// obj.Print(); //As is the compiler will complain, because obj is a const //object inside this function and the Print function is non-const
//}
//Using const_cast you can do this...
void SomeFunction(const &MyClass obj)
{
const_cast<MyClass &>(obj.Print());
}
disclaimer: This example is not the end all be all, just shows a simple use case, whether this case makes any sense... if it helps understand the concept for just 1 person, good enough for me.
I'm with computerquip and Vlykarye -- you should never, ever use const_cast<> !!
But I have been forced to use clanmjc's approach in legacy code, where the proper fix (e.g. make MyClass::Print const) would have created so much ripple in the rest of code base -- due to const laziness -- that we had to break the no-const_cast rule. But we did know the function we were calling could and should have been const in the first place!
Basically using const_cast is just shooting yourself in the foot:
1)Constness in C++ have nothing to do with runtime: a const variable can be stored in a modifiable hardware location. It is just an information you give to the compiler to say "I promise i will never change this variable during runtime"
2) With this promise, the compiler can do a lot of optimisations and considers a const variable will be the same everywhere it appears.
3) So if you break this promise with const_cast, stange things could appear. Consider this piece of code:
int main()
{
const int i = 5;
const_cast<int&>(i) = 8;
cout << i;
}
In theory this must output 8 but in practice a lot of compilers (including gcc and MSVS) will output 5 because you promised "i" will not change so they can replace the i of cout << i by 5.
And now if I define this function:
1 2 3 4
void c(constint& i)
{
cout << i;
}
and replace the last code by:
1 2 3 4 5 6
int main()
{
constint i = 5;
const_cast<int&>(i) = 8;
c(i);
}
This time we get 8 because the real "i" will be output. The compiler cannot guess the value of "i" in function "c".
That said, there are places in code where we have used const_cast and not because we made any promises, but because we had to use what the standard library gave us.
e.g. - We've used std::sets where the element type had state information that does not have anything to do with equivalence. std::set elements themselves are keys, therefore any iterator to a set is a const_iterator, const_cast has to be used to change the state information (they could have made this info mutable and maybe they should, but they didn't). That said, changing this info does not mean that they key itself needs to be rehashed, because like I said earlier it has nothing to do with equivalence.
chanmjc => I met exactly the same problem and I think I resolved it by splitting the key into the key part and the value part into two separate class to use a map instead of a set.
But I agree this may be difficult if this class is used everywhere as this may involve a big refactoring.
Also, I'm unsure of what you mean every iterator to an std::set must be a const_iterator.
When you perform a find and get back an iterator to an element of a set, that iterator is a const_iterater, because the element the iterator points to is a key and should not be mutable. (at least in my STL implementation)
EDIT: I *think* you mean an element that's set cannot be changed and instead, you must erase and then add a new element...?
This is correct, if I want to change something that would change the sortdedness of the set, then I would first need to erase, then add. What I'm talking about though is in place modifications that do not effect sortdedness (and are transparent to everyone).
@aquaz - We have a custom container that we use for lockless threading and cannot split it (at least not easibly). Using const_cast in this scenario has no drawback really
To quote Scott Meyers for a second time in the same thread:
If portability is not a concern, you want to change the value of an element in a set or multiset, and your STL implementation will not let you get away with it, go ahead and do it. Just be sure not to change a key part of the element, i.e., a part of the element that could affect the sortedness of the container.
Yes we thought about using mutable, but we wanted to ensure that later on when other developers are using said container, that they be forewarned by the compiler.