Компаратор C++ std::set

Это код:

struct comp
{
    bool operator()(Reputation *one, Reputation *two)
    {
        if (one->Amount < 0 && two->Amount >= 0)
            return false;
        if (one->Amount >= 0 && two->Amount < 0)
            return true;

        if (one->Amount >= 0)
            return one->Amount <= two->Amount;
        else
            return one->Amount >= two->Amount;
    }
};

И это проблема:

Ошибка утверждения отладки!
Файл: ..\VC\include\xtree
Строка: 638

Выражение: неверный оператор‹

После этого я могу выбрать «Прервать», «Повторить попытку» или «Игнорировать». Если я выберу игнорировать, появится много других (идентичных), но в итоге все работает отлично.

Проблема возникает, когда я вставляю Reputation с ->Amount == в одну из ранее вставленных репутаций *, но я не уверен в последнем.

Любая помощь будет принята с благодарностью

РЕДАКТИРОВАТЬ: Порядок, в котором я хочу их упорядочить, - это сначала положительные в порядке возрастания, затем отрицательные в порядке убывания. Пример: 1 5 10 11 11 20 50 -1 -5 -50


person Thomas Bonini    schedule 29.06.2009    source источник


Ответы (3)


Вы должны определить отношение, которое является иррефлексивным, как и <, поэтому измените <= на < и '>=' на '>' в последних нескольких сравнениях вашего метода. Это то, что VC++ диагностирует.

Кроме того, при правильно закодированном <-подобном операторе, если два элемента a и b таковы, что a ‹ b и b ‹ a оба являются ложными, эти элементы считаются эквивалентными, и, таким образом, в набор будет вставлен только один (неважно, будет ли элементы могут быть различимы с помощью какого-либо другого сравнения: имеет значение только отношение эквивалентности, подразумеваемое компаратором).

person Alex Martelli    schedule 30.06.2009
comment
Спасибо, это исправлено. Очень признателен! - person Thomas Bonini; 30.06.2009
comment
Рад, что помог исправить проблему с ошибкой утверждения отладки, но, пожалуйста, прочитайте мое последнее редактирование об уникальности - вам нужен мультимножество, как говорит @Kasprzol, если вы хотите сохранить несколько элементов, которые не различимы с помощью компаратора< /я>. - person Alex Martelli; 30.06.2009
comment
Да, я уже тоже переделал его в мультисет по совету Каспрозла! - person Thomas Bonini; 30.06.2009
comment
Не могли бы вы помочь мне с аналогичной проблемой? Я не могу решить эту проблему, даже если я получаю то же самое утверждение отладки! ошибка с установленным компаратором? ссылка на мой вопрос находится здесь: [ссылка] stackoverflow.com/questions/5823469/ - person sactiw; 28.04.2011

Элементы в std::set должны быть уникальными! (и менее сравнимы) Если вы хотите иметь несколько элементов с одинаковым значением (например, предоставленный вами образец), используйте std::multiset.

см.: http://www.cppreference.com/wiki/stl/set/start и http://www.cppreference.com/wiki/stl/multiset/start

person Kasprzol    schedule 30.06.2009
comment
Я преобразовал его в std::multiset, но возникает точно такая же проблема. - person Thomas Bonini; 30.06.2009

Вы не можете вставлять одинаковые значения в std::set, для этого требуются уникальные значения. Используйте std::multiset.

Для вашего забавного заказа это работает:

struct comp
{
    bool operator()(const Reputation *a, const Reputation *b)
    {
        if (a->Amount < 0 && b->Amount < 0)
            return a->Amount > b->Amount;
        else if (a->Amount < 0) return false;
        else if (b->Amount < 0) return true;
        else return a->Amount < b->Amount;
    }
};
person stefanB    schedule 30.06.2009
comment
Набор представляет собой набор указателей. Все они уникальны, даже если некоторые из них имеют одинаковую -›Amount. Вот точный код: multiset‹Reputation*, comp› sorted; for (Reputation *rep = Reputation::GetReputationTable(); rep-›Id; ++rep) sorted.insert(rep); - person Thomas Bonini; 30.06.2009
comment
О, хорошо, из примера было неясно... но да, если вы храните указатели, используйте указатели - person stefanB; 30.06.2009