ошибка компиляции при удалении элемента STL std :: set по ключу - PullRequest
1 голос
/ 26 мая 2011

У меня есть следующий код, в котором я храню набор итераторов std :: set для контейнера STL размером int s и стираю элемент по ключу (где ключ является итератором для контейнера STL).Код компилируется и выполняется должным образом (компилятор VC 2008), если контейнер является std :: vector, но не может скомпилироваться, если контейнер является std :: list

using namespace std;

typedef vector< int > Container;     //--> fails to compile if 'vector' is changed to 'list'
typedef Container::iterator IntIt;

set< IntIt > itSet;
Container c;
c.push_back (1);
c.push_back (2);
c.push_back (3);

IntIt it = c.begin ();
itSet.insert (it++);
itSet.insert (it++);
itSet.erase (c.begin ()); //--> The problematic line

Ошибка компиляции:

c: \ Program Files (x86) \ Microsoft Visual Studio 9.0 \ VC \ include \ functions (143): ошибка C2784: 'bool std :: operator <(const std :: _ Tree <_Traits>>&, const std :: _ Tree <_Traits> &) ': не удалось вывести аргумент шаблона для' const std :: _ Tree <_Traits> & 'из' const IntIt '

Так мне кажетсяошибка в том, что компилятор интерпретирует один из < шаблона как оператор smaller than - но я не могу понять, почему или как это исправить.

1 Ответ

5 голосов
/ 26 мая 2011

Проблема вызвана тем, что list::iterator не имеет определенного сравнения. Тип значения std::set требует строгого слабого упорядочения.

A vector поддерживает итераторы с произвольным доступом, которые имеют порядок. Список требуется только для поддержки двунаправленных итераторов, которые не имеют порядка (конечно, реализация может поддерживать итераторы с произвольным доступом и для списков, поэтому на некоторых компиляторах это может работать).

Чтобы исправить это, вам нужно написать функцию сравнения самостоятельно. Проблема в том, что единственный способ определить порядок двух итераторов в list - это пройтись от одного к другому, что требует линейного времени.

...