c++iteratorstdstdsetreverse-iterator

How come 2 uninitialized std::set::iterator are equal?


When std::set<>::iterator is uninitialized, it is not equal to any other iterator in the set, but it is equal to other uninitialized iterators.

Is this GCC-specific implementation? (Is the uninitialized iterator actually initialized to an invalid value?)

#include <stdio.h>
#include <iostream>
#include <set>
#include <vector>

int main()
{
    std::set<int> s;
    std::set<int>::reverse_iterator inv = s.rend();
    std::cout << (inv == s.rend()) << "\n";
    std::cout << (inv == s.rbegin()) << "\n";
    s.insert(5);
    std::cout << (inv == s.rend()) << "\n";
    std::cout << (inv == s.rbegin()) << "\n";
    // invalidate
    inv = std::set<int>::reverse_iterator();
    std::cout << (inv == s.rend()) << "\n";
    std::cout << (inv == s.rbegin()) << "\n";

    auto inv2 = std::set<int>::reverse_iterator();
    std::cout << (inv == inv2) << "!!!\n";

    return 0;
}

prints:

1
1
0
1
0
0
1!!!

Live example: https://onlinegdb.com/r1--46u_B


Solution

  • How come 2 uninitialized std::set::iterator are equal?

    They are not uninitialised. They are value initialised. A value initialised iterator is singular: it does not point to any container.

    Behaviour of reading an uninitialised value would be undefined, but that's not what you do in the program.

    it is not equal to any other iterator in the set

    Comparison between input iterators is only defined for iterators to the same range. A singular iterator does not point to same range as any non singular iterator, so the comparison is undefined.

    but it is equal to other uninitialized iterators.

    Two singular iterators always compare equal.

    Is this a GCC-specific, non-portable implementation?

    Comparing singular iterator to non singular is undefined. Undefined behaviour is generally "non-portable", even within the same compiler version (unless compiler specifies the behaviour in which case it is non-portable to other compilers).

    Singular iterators in general are standard since C++14, for all forward iterators.