First you have it the wrong way around.
You should not use the mutating version to supply data to the non-mutating function:
const int& MyClass::operator[](int index)const {
return const_cast<int&>(const_cast<MyClass&>(*this)[index]);
}
What happens if operator[]
is modified and does mutate slightly the internal state? By casting away the constness you have opened up your class to undefined behavior. You should NEVER cast away constness. If you must you can use const_cast to add constness, but removing it is so dangerous that this should be looked at as breaking code.
If you had written it the other way around:
int& MyClass::operator[](int index) {
return const_cast<int&>(const_cast<MyClass const&>(*this)[index]);
}
This is better. Because if you change the operator[]
so that it actually mutates the class it will generate a compiler error and thus prevent you from accidentally getting undefined behavior.
But personally I prefer to add another helper method and thus remove all athe casting:
private:
// NOTE: This is not a perfect solution for all situations.
// But it works for 99% of situations and keeps the code clean
// For the remaining situations switch back to use const cast
// **BUT** always add never remove constness from an object.
// Never make public as it is const and gives away an internal reference.
// Only use via the public API
int& get(int index) const
{
return stuff[index];
}
public:
// Keep the API simple/clean and DRY
// move all the work to private methods.
int& operator[](int index) { return get(index);}
int const& operator[](int index) const { return get(index);}
Answer to comment below:
I would not use it for const/non-const iterators
const_iterator begin() const {return const_iterator(<X>);}
iterator begin() {return iterator(<X>);}