Почему я не могу использовать оператор += в итераторе списка?

У меня есть итератор из std::list<std::string>, но когда я пытаюсь продвинуть его, используя +=, Я получаю ошибку компиляции.

Код является:

#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";
    }
}

Если я скомпилирую это с помощью clang++ -std=c++11 -o li li.cpp, Я получил:

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

Почему я не могу использовать += с этим итератором?

3 ответа

Решение

Итератором для std::list является BidirectionalIterator, который не поддерживает operator+= как RandomAccessIterator.

Ты можешь использовать operator++, который поддерживается InputIterator (в том числе BidirectionalIterator), что-то вроде

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

Но это безобразно. Лучший способ, как вы прокомментировали, использовать вместо него std:: advance (или std:: next (начиная с C++11)), который можно использовать с InputIterator (включая BidirectionalIterator), а также использует возможности, поддерживаемые RandomAccessIterator,

(акцент мой)

сложность

Linear.

Однако если InputIt дополнительно отвечает требованиям RandomAccessIterator, сложность постоянна.

Таким образом, вы можете просто использовать его без учета категории итератора, std::advance сделает лучший выбор для вас. например

std::advance(iter, 3);

или же

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

Причина в том, что += Оператор не определен для двунаправленного итератора, который вы используете.

Для всех итераторов есть как минимум:

  • Копируемый и разрушаемый, т.е. X b(a); а также b = a;
  • Может быть увеличено, т.е. ++a а также a++

Все остальное зависит от типа итератора, проверьте таблицу здесь:

Как видите, итератор с произвольным доступом сделает свое дело.

std::list::iterator не является итератором произвольного доступа Невозможно "перескочить" несколько элементов в списке, вы должны перебирать список, пока не достигнете нужного элемента. Ты можешь использовать std::advance который выведет лучший способ продвижения итератора на основе категории итератора. В случае std::list::iterator он будет увеличивать итератор в цикле.

Другие вопросы по тегам