简体   繁体   中英

C++ const_iterator to iterator for forward_list

As per this question , and assuming I have a mutable reference to the container itself , the constness of an iterator can be safely removed using:

foo::const_iterator cit = ... ;
foo::iterator it = c.erase( cit, cit );

However, this doesn't seem to work for forward_list 's equivalent, erase_after , as per this code::

#include <iostream>
#include <forward_list>

typedef std::forward_list<int>::const_iterator CIT;
typedef std::forward_list<int>::iterator IT;

int main()
{
    std::forward_list<int> m{1, 2, 3};

    CIT cit = m.begin();
    IT it = m.erase_after(cit, cit); // Segmentation fault!

    std::cout << *it;
}

So is there any way to remove the constness of a const iterator for this class? Preferably not by iteration!

You have a segmentation fault because you're violating the precondition of erase_after() , which states that the range (first, last) passed to

iterator erase_after(const_iterator first, const_iterator last);

should be a valid range. Note that this is () -type of range, not [) , so both ends are excluded. That's why (cit, cit) is not a valid range for erase_after .

GCC with -D_GLIBCXX_DEBUG complains :

Error: function requires a valid iterator range (__pos, __last) , __pos shall be before and not equal to __last .

although I think it's tricky and STL should provide a normal way to do that, there is also a solution by insert_after , because:

iterator insert_after(const_iterator position, size_type n, const T& x);

Preconditions: position is before_begin() or is a dereferenceable iterator in the range [begin(), end()) .

Effects: Inserts n copies of x after position.

Returns: An iterator pointing to the last inserted copy of x or position if n == 0 .

it returns pos itself, if n == 0 .

if you don't want to create a temporary object of T , you can use:

template<class InputIterator>
  iterator insert_after(const_iterator position, InputIterator first, InputIterator last);

or

iterator insert_after(const_iterator position, initializer_list<T> il);

and provide an empty sequence or initializer list.

By iteration you can do it like:

IT it (m.begin());
for ( CIT cit = m.begin(); cit != m.end(); ++cit )
{
   std::advance (it, std::distance<CIT>(it, cit ) );
   // do changes on it
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM