4
votes

So I encountered a weird iterator bug ONLY on std::set : I'm unable to do a simple thing like (it + 1) on an iterator without a compilation error Try to compile this yourself :

void setBug()
{
    std::set<int> values;

    for (auto it = values.cbegin();
         it != values.cend(); ++it) {
        if ((it + 1) != values.end())
            values.insert(*it / *(it + 1));
    }
}

error: invalid operands to binary expression ('std::_1::_tree_const_iterator *, long>' and 'int') if ((it + 1) != values.end())

error: invalid operands to binary expression ('std::_1::_tree_const_iterator *, long>' and 'int') values.insert(*it / *(it + 1));

compiler version : Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn) Target: x86_64-apple-darwin13.1.0 Thread model: posix

I found a dirty solution : (auto it2 = ++it ; --it) which works, but this is really dirty...

Has somebody an explanation ? Is std::set broken ?

Thanks.

1
it is a bidirectional iterator, not a random access oneAbhishek Bansal
auto it2 = it; ++it2; would be cleaner than your dirty solution.Jonathan Wakely

1 Answers

15
votes

std::set iterators are bidirectional iterators. These do not support increment via the addition operator. You need to increment then step by step, or use std::next or std::advance, both of which which do the same behind the scenes. This operation will be O(N) regardless.