Why does const_iterator
not provide a const_iterator::base()
function, to obtain corresponding non-const iterator
like reverse_iterator
does?
Considering following pseudocode (say, geometric algorithm):
std::container< point > universe;
auto it = std::cbegin(universe);
std::list< decltype(it) > interesting_subset = sieve(it, std::cend(universe));
auto structure = algorithm(interesting_subset);
where universe
is all the input points. After sieve()
-ing the interesting_subset
contains iterators to subset of universe
's members. Following algorithm()
constructs a resulting structure
from interesting_subset
, which consists of references (iterators) to members of the universe
.
At the end, I want to change the point
s, containing into resulting structure
(say, shift them). But equally I want to protect them from modyfining during algorithm
action, and therefore I used std::cbegin
/std::cend
as opposite to std::begin
/std::end
. Finally I have only const_iterator
references to source point
s.
This is a very use case for iterator std::container< T >::const_iterator::base() const
member function I want to be present into STL containers.
Why does const_iterator not provide a const_iterator::base() function, to obtain corresponding non-const iterator like reverse_iterator does?
To maintain const-safety. Providing such function would be very dangerous as already discussed here at length.
At the end, I want to change the points, containing into resulting structure (say, shift them). But equally I want to protect them from modyfining during algorithm action, and therefore I used std::cbegin/std::cend as opposite to std::begin/std::end. Finally I have only const_iterator references to source points.
Well, you're asking for the wrong thing with the base
-member. Sure it would solve your problem, but as said, it's just too dangerous. Let me rephrease a question for you:
If I have a
const_iterator
to an object and non-const access to the container, how do I efficiently (in constant time) get aniterator
to the referred object?
Here's a fancy trick to do exactly that:
template <typename Container, typename ConstIterator>
typename Container::iterator remove_constness(Container& c, ConstIterator it)
{
return c.erase(it, it);
}
I don't take any credit for the trick. I found it from https://stackoverflow.com/a/10669041/2079303 and they credit Howard Hinnant and Jon Kalb
As discussed in the comments of that answer, this trick works with all standard containers, but not necessarily with all possible standard-compliant third-party containers because they're not required to provide erase
.
Personally, I would prefer that standard containers had a non-const member function that would convert a given const_iterator
to an iterator
, but they don't, so you need to work around it.