Keeping std::list iterators valid through insertion
c++, iterator, stdlist
Solution
if (readpos == buf.begin())
{
buf.insert(buf.end(), newdata.begin(), newdata.end());
readpos = buf.begin();
}
else
{
--readpos;
buf.insert(buf.end(), newdata.begin(), newdata.end());
++readpos;
}
Not elegant, but it should work.
Problem
Note: This is not a question whether I should "use list or deque". It's a question about the validity of iterators in the face of `insert()`. This may be a simple question and I'm just too dense to see the right way to do this. I'm implementing (for better or worse) a network traffic buffer as a `std::list<char> buf`, and I'm maintaining my current read position as an iterator `readpos`. When I add data, I do something like ``` buf.insert(buf.end(), newdata.begin(), newdata.end()); ``` My question is now, how do I keep the `readpos` iterator valid? If it points to the middle of the old `buf`, then it should be fine (by the iterator guarantees for std::list), but typically I may have read and processed all data and I have `readpos == buf.end()`. After the insertion, I want `readpos` always to point to the next unread character, which in case of the insertion should be the first inserted one. Any suggestions? (Short of changing the buffer to a `std::deque<char>`, which appears to be much better suited to the task, as suggested below.) Update: From a quick test with GCC4.4 I observe that deque and list behave differently with respect to `readpos = buf.end()`: After inserting at the end, readpos is broken in a list, but points to the next element in a deque. Is this a standard guarantee? (According to cplusplus, any deque::insert() invalidated all iterators. That's no good. Maybe using a counter is better than an iterator to track a position in a deque?)