q0987
q0987

Reputation: 36012

Implementation of operator!= for Iter Class

Based on the implementation of Iter, I have difficulties to understand operator!= and don't understand why it doesn't check _p_vec?

This is the suggested implementation of operator!= that ONLY compares the _pos.

class Iter
{
    public:
    Iter (const IntVector* p_vec, int pos)
        : _pos( pos )
        , _p_vec( p_vec )
    { }

    // these three methods form the basis of an iterator for use with
    // a range-based for loop
    bool operator!= (const Iter& other) const
    {
        return _pos != other._pos;
    }
    ...
    ...
    private:
        int _pos;
        const IntVector *_p_vec;
};

However, I think the correct way to do this as follows. In other words, we have to compare both _pos and _p_vec.

bool Iter::operator!= (const Iter& other) const
{
    return _p_vec != other._p_vec || _pos != other._pos;
}

Question> Whose code is correct?

===Update on how std::vector works on comparison of iterator====

std::vector<int> vecOne { 1, 2, 3};
std::vector<int> vecTwo { 4, 5, 6};

auto iterOne = vecOne.begin();
std::advance(iterOne, 1);

auto iterTwo = vecTwo.begin();
std::advance(iterTwo, 1);

if ( iterOne == iterTwo)
    std::cout << "iterOne == iterTwo" << std::endl;
else
    std::cout << "iterOne != iterTwo" << std::endl;

Output is : iterOne != iterTwo

However,

std::vector<int> foo;
std::vector<int> bar;

if ( foo.begin() == bar.begin() )
    std::cout << "foo.begin() == bar.begin()" << std::endl;
else
    std::cout << "foo.begin() != bar.begin()" << std::endl;

Output is : foo.begin() == bar.begin()

GCC (version 4.7.1)

Upvotes: 0

Views: 122

Answers (2)

leemes
leemes

Reputation: 45745

Also comparing the underlying container reference is an improvement to make sure that, for example, the begin() iterators of two different containers compare equal.

However, iterators of different containers are rarely compared (when using STL algorithms, they never will). So this might be considered an optimization. Think of a loop in which you step from begin() to end(), so the only iterators you are comparing are the "current" one and end(), which are of the same container.

Comparing iterators of standard containers (vector, etc.) is considered undefined behavior. Indeed, since they never are compared in (good) code (for example the standard algorithms), it doesn't have to define a behavior for such cases.

So the author of this Iter class might also want to come back to this point and say: "Comparing iterators of different vectors is undefined behavior."

This being said, if you want to ensure that you never compare iterators of different containers, leave out this check and maybe assert it for debug builds (but don't check it in release builds).

A good example where you might want to compare iterators of different containers is for linked lists, where you define the end of the list being a null pointer (or a pointer to a static null item instance). Consider the iterator being a pointer to a linked list item; in this case, the end() iterator is just a null pointer (or points to this null item). It is the same one for all containers, so you can't implement the check in your comparison method in such cases. Maybe this is one of the reasons why such a comparison isn't defined -- it should return "unequal" when comparing end iterators of different lists, but it can't.

Upvotes: 2

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275976

As a general rule, users of iterators are not supposed to compare iterators from different containers. In the standard library, doing so is undefined behavior.

So assuming you are only trying to create iterators that are as robust as standard library ones, comparing the container is not required. However, if you have the pointer to container around, then it would be polite to check that the containers match at least in debug, then assert that you shouldn't be making this comparison.

You are free to check it in release as well, but if your iterator using code is also supposed to work with standard containers, then relying on iterators from different containers comparing not equal is not advised.

See comparing iterators from different containers for someone talking about how it is undefined behavior.

Upvotes: 2

Related Questions