Reputation: 3997
The C++11 standard has changed the signature of the erase()
methods of standard containers: they now accept const_iterator
s instead of iterator
s. The rationale is explained in this document:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2350.pdf
Now, if one implements std::vector<T>
in a straightforward way, it is possible to use directly const T *
and T *
as const and mutable iterator types respectively. So in the erase()
method we might have code like this:
iterator erase(const_iterator it)
{
...
for (; it != end() - 1; ++it) {
// Destroy the current element.
it->~T();
// Move-init the current iterator content with the next element.
::new (static_cast<void *>(it)) T(std::move(*(it + 1))); // FAIL
}
...
}
The problem now is that, since it
is a const pointer, the static cast will fail.
Is it legal in this case to cast away the constness from it
? Note that it
never points to a const
object (the objects stored in the vector are never const
), and that the calling method (erase()
) is not const
as well.
EDIT: thanks for all the replies. I wanted to respond here to some comments below.
This code comes from a custom vector class (with a similar interface to std::vector
) that implements the small buffer optimisation on top of an unrestricted union. The iterators are naked pointers because they need to be the same type both when the vector is using static storage and when it is using dynamic storage, and this seems the most natural way of achieving such result.
The cast to void *
is just a matter of habit and consistency within the codebase when interacting with unitialised storage.
Upvotes: 4
Views: 222
Reputation: 103693
Since erase
is non-const, yes, you can safely cast away const on the element. However, note that this is not necessary, since a non-const iterator can be obtained from the const iterator:
iterator non_const = begin() + (it - begin());
And that can be used to iterate over the vector.
Upvotes: 6