std :: set итератор с одинаковым ключом и разными компараторами - PullRequest
0 голосов
/ 16 мая 2018

Пытаясь решить проблему, я начал думать об этом - учитывая user-defined class и 2 comparators для него, скажем, у нас есть 2 набора std::set<user_class,comparator_inc> и std::set<user_class,comparator_dec>, где comparators сортируется по возрастанию иуменьшение значения на значение в user_class (возможно, простое int).Вот мой код:

#include <iostream>
#include <set>

using std::cout;
using std::endl;
using std::set;

struct A
{
    int val;
};
struct c_inc
{
    bool operator()(const A& first,const A& second) const
    {
        return first.val > second.val;
    }
};
struct c_dec
{
    bool operator()(const A& first,const A& second) const
    {
        return first.val < second.val;
    }
};

int main()
{
    set<A,c_inc> s1;
    set<A,c_dec> s2;

    auto x = s1.insert({1});
    cout << x.first->val << endl;

    x = s2.insert({1});
    x = s2.insert({0});

    cout << x.first->val << endl;   
}

Мой вопрос таков: определено ли поведение для повторного назначения x для вывода insert в set с тем же Key, но другим компаратором?Есть ли проблема с этим видом использования?Это определено в стандарте где-то, что это должно быть, или это зависит от реализации?

Поскольку код компилируется, я думаю, что тип return insert в обоих случаях одинаков - верно ли это предположение?

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Я думаю, что это зависит от реализации.

Концептуально тип возвращаемого значения s1.insert и s2.insert различен;особенно они имеют разные типы итераторов, например std::set<A,c_inc>::iterator и std::set<A,c_dec>::iterator.А способ определения типа std::set::iterator определяется реализацией.

[set.overview] / 2

using iterator               = implementation-defined; // see [container.requirements]
using const_iterator         = implementation-defined; // see [container.requirements]
0 голосов
/ 16 мая 2018

Технически говоря, на это не стоит полагаться.

Поскольку код компилируется, я думаю, что возвращаемый тип вставки в обоих случаи одинаковы - верно ли это предположение?

Нет, это не так. Представьте себе этот простой пример:

template<class T>
struct set {
   struct iterator { /*...*/ };
};

В этом случае set<int>::iterator определенно отличается от set<double>::iterator.

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

...