KiYugadgeter
KiYugadgeter

Reputation: 4014

Why can't I use += operator on a list iterator?

I have a iterator from a std::list<std::string>, but when I attempt to advance it using +=, I get a compilation error.

The code is:

#include <list>
#include <iostream>
#include <string>
int main() {
    std::list<std::string> x;

    x.push_front("British");
    x.push_back("character");
    x.push_front("Coding is unco");
    x.push_back("Society");
    x.push_back("City Hole");
    auto iter = x.begin();
    iter += 3;
    //std::advance(iter, 3);
    x.erase(iter);

    for (auto &e: x) {
        std::cout << e << "\n";
    }
}

If I compile this using clang++ -std=c++11 -o li li.cpp, I get:

li.cpp:13:10: error: no viable overloaded '+='
    iter += 3;
    ~~~~ ^  ~
1 error generated.

Why can't I use += with this iterator?

Upvotes: 4

Views: 3113

Answers (3)

songyuanyao
songyuanyao

Reputation: 172894

The iterator for std::list is BidirectionalIterator, which doesn't support operator+= like RandomAccessIterator.

You can use operator++, which is supported by InputIterator (including BidirectionalIterator), something like

++iter;
++iter;
++iter;

But it's ugly. The best way is as you commented, to use std::advance (or std::next (since C++11)) instead, which could be used with InputIterator (including BidirectionalIterator), and also takes advantage of the features supported by RandomAccessIterator.

(emphasis mine)

Complexity

Linear.

However, if InputIt additionally meets the requirements of RandomAccessIterator, complexity is constant.

So you can just use it without considering about the category of the iterator, std::advance will do the best choice for you. e.g.

std::advance(iter, 3);

or

iter = std::next(iter, 3);

Upvotes: 17

Beginner
Beginner

Reputation: 5457

The reason is simply that the += operator is not defined for the Bidirectional iterator you are using.

For all iterators there is at least:

  • Copy-assignable and destructible, i.e. X b(a); and b = a;
  • Can be incremented, i.e. ++a and a++

Everything else depends on the type of iterator check the table here:

enter image description here

As you see a random-access iterator would do the trick.

Upvotes: 6

Fran&#231;ois Andrieux
Fran&#231;ois Andrieux

Reputation: 29023

A std::list::iterator is not a Random Access Iterator. It is not possible to "jump ahead" several elements in a list, you must iterate through the list until you reach the desired element. You can use std::advance which will deduce the best way to advance the iterator based on the iterator category. In the case of a std::list::iterator it will increment the iterator in a loop.

Upvotes: 3

Related Questions