I'm having an issue which I cannot quite find the cause of.
At a certain point in my code I'm returning the distance between two std::vector iterators, one being the result of an insert operation on a vector and the other pointing to the beginning of the vector. The idea is to return the index of the newly inserted object.
Everything works perfectly when I phrase the code like this
const_iterator (or auto) it = insert(object);
return it - begin();
However, if I try to make a one liner out of it
return insert(object) - begin();
I get the aforementioned "Vector Iterators Incompatible" assertion.
begin() is implemented as:
MyClass::iterator MyClass::begin()
{
return m_container.begin();
}
and insert() is implemented as:
MyClass::iterator MyClass::insert(MyObject *object)
{
if (object)
{
const_iterator it = std::lower_bound(begin(), end(), object, DereferencedLess<MyObject >());
if (it == end() || *(*it) != *object)
return m_container.insert(it, object);
}
return end();
}
Brief outline of the class:
MyClass {
...
iterator begin();
const_iterator begin() const;
iterator insert(MyObject*);
...
protected:
std::vector<MyObject*> m_container;
}
and for completeness' sake
template<typename T>
struct DereferencedLess
{ inline bool operator()(const T *p1, const T *p2) const { return *p1 < *p2; } };
I would very much like to understand why the assertion happens. From what I can see the iterators are of the same type and both insert() and begin() are working on the same vector. All the necessary typedefs are in place as well.
vector::insert
invalidates the iterators. In expression insert(object) - begin()
begin()
can be called before or after insert
. If it is called before than it is invalidated by insert()
. Order of evaluation:
Order of evaluation of the operands of almost all C++ operators (including the order of evaluation of function arguments in a function-call expression and the order of evaluation of the subexpressions within any expression) is unspecified. The compiler can evaluate operands in any order, and may choose another order when the same expression is evaluated again.
Whereas when you do:
const_iterator (or auto) it = insert(object);
return it - begin();
begin()
is called after insert()
and hence returns a valid iterator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With