set_union для произвольных структур - где я ошибся? - PullRequest
0 голосов
/ 09 июня 2011

Это продолжение моего предыдущего поста , в котором говорилось, что делать хорошо, но его реализация не работала: S. Все, что я хочу, это set_union (и другие операции над множествами) в классе алгоритма C ++ для работы с моими структурами. Вот что у меня есть.

Моя структура:

struct player {
    int lbl;
    int lbl1;

    bool operator<(const player &t) const {
        return (lbl < t.lbl && lbl1 < t.lbl);
    }
};

, который определяет оператор <в моей структуре, т. Е. Один игрок «меньше», чем другой игрок, если оба его ярлыка (целые числа) меньше ярлыков другого игрока. </p>

Затем для выполнения set_union я делаю это:

    player p1;
    p1.lbl = 1;
    p1.lbl1 = 3;

    player p2;
    p2.lbl = 3;
    p2.lbl1 = 5;

    player p3;
    p3.lbl = 2;
    p3.lbl1 = 8;

    player p4;
    p4.lbl = 1;
    p4.lbl1 = 7;

    vector<player> v1;
    vector<player> v2;
    v1.push_back(p2);
    v1.push_back(p1);
    v2.push_back(p3);
    v2.push_back(p4);

    sort(v1.begin(), v1.end());
    sort(v2.begin(), v2.end());

    vector<player> v;
    set_union(v1.begin(), v1.end(), v2.begin(), v2.end(),
              back_inserter(v));

    for(int i = 0; i < v.size(); i++) {
        cout << v.at(i).lbl << ", " << v.at(i).lbl1 << endl;
    }

который печатает:

1, 3
3, 5

когда он должен был печатать

1, 3
3, 5
2, 8
1, 7

потому что это объединение. Возможно, я где-то ошибся в определении структуры? Тот же самый set_union работает с векторами как строк, так и целых чисел, так что это, вероятно, моя структура плеера?

Спасибо.

дополнительный код

Ниже приведен мой фактический структурный код (с исправлениями, предложенными Навазом). Первоначально я опубликовал упрощенную версию, но, возможно, мне нужно опубликовать все это:

struct player {
    int i;
    int lbl;
    int lbl1;
    argument argu;
    string player_name;

    player(string player_name);

    bool operator<(const player &t) const {
        if ( lbl != t.lbl )
            return lbl < t.lbl;
        return lbl1 < t.lbl1;
    }

};

1 Ответ

7 голосов
/ 09 июня 2011

Вы должны реализовать Строгий слабый порядок , поскольку ассоциативные контейнеры , такие как std::set, std::multiset, std::map, std::multimap, требуют, чтобы порядок элементов был Strict Weak Ordering. И в вашем случае set_union оперирует данными в соответствии с правилами std::set, что требует строгого слабого порядка , но ваша функция сравнения не реализует его. Отсюда и проблема!

Также обратите внимание, что документация по std :: set_union в cplusplus гласит:

Объект функции сравнения, который, принимая два значения того же типа, что и значения, содержащиеся в диапазоне, возвращает true, если первый аргумент идет перед вторым аргументом в определенном строгом слабом порядке , который он определяет, и false в противном случае.

Итак, ваша функция сравнения должна быть такой:

struct player {
    int lbl;
    int lbl1;

    bool operator<(const player &t) const 
    {
        if ( lbl != t.lbl )
               return lbl < t.lbl;
        return lbl1 < t.lbl1;
    }
};

Это даст правильный вывод. Посмотрите это онлайн демо:

http://www.ideone.com/d4Kob

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...