std :: установить использование оператора - PullRequest
0 голосов
/ 07 февраля 2019

Этот вопрос как бы связан с моим другим вопросом здесь: ссылка (см. Обсуждение в комментариях).По сути, у меня была следующая проблема:

У меня есть класс node.Имеет несколько полей, наиболее важные из них: G, H и pos (pos - это Qt's QPoint, но я переписал его ради примера для своего собственного класса Point.См. Пример ниже:

#include <algorithm>
#include <iostream>
#include <memory>
#include <set>

class Point
{
public:
    int _x, _y;
    Point() : _x(0), _y(0) {}
    Point(int x, int y) : _x(x), _y(y) {}
    bool operator==(const Point& p) const { return _x == p._x && _y == p._y; }
    bool operator!=(const Point& p) const { return _x != p._x && _y != p._y; }
};

class node
{
public:
    node() {}
    node(const Point& p) : pos(p) {}
    bool operator==(const node& o) const { return pos == o.pos; }
    bool operator==(const Point& o) const { return pos == o; }
    bool operator!=(const node& o) const { return pos != o.pos; }
    bool operator<(const node& o) const { return G + H < o.G + o.H; }
    Point pos;
    std::shared_ptr<node> parent;
    int G = 0;
    int H = 0;
};

int main()
{
    node n1(Point(6, 7));
    n1.G = 1;
    n1.H = 1;
    node n2(Point(1, 1));
    n2.G = 2;
    n2.H = 2;
    node n3(Point(2, 2));
    n3.G = 1;
    n3.H = 1;
    std::set<node> nodes;
    nodes.insert(n1);
    nodes.insert(n2);
    nodes.insert(n3);
    auto min = (*std::min_element(nodes.begin(), nodes.end())).pos;
    std::cout << min._x << " " << min._y << '\n';
    std::cout << nodes.size() << '\n';
}

Вывод этой программы:

>main.exe
6 7
2

Итак, поиск самого низкого элемента был успешным (с использованием operator<).Я хотел. Но, как вы видите, три node, которые я создал, имеют разные поля .pos (в основном, координаты). Поэтому я хотел бы, чтобы все они присутствовали в наборе. Другими словами, вы можете сказать,что "уникальность" каждого узла должна определяться полем .pos (фактически используя operator== этого поля, которое я определил выше). И один из узлов считается не уникальным, потому что std::set используется для operator<сравнивая его элементы. Таким образом, n1 и n3 имеют одинаковое значение G+H, и они считаются равными (2 во второй строке вывода - это число элементов набора -> 2, а не 3).

До того, как я узнал об использовании std::set operator< длясравните на равенство, я написал operator== и operator!=, думая, что набор будет использовать один из них для сравнения объектов моего класса.Но он использует operator<.

Так что мой вопрос здесь, почему на самом деле он использует этот оператор.Не проще ли использовать operator== или operator!=?

Для меня это несколько усложняет работу, потому что мне нужно придумать другой способ написать operator< или использовать другой контейнер (поэтому пишу лямбды) или я могу использовать .pos сравнение в operator< и переписать std::min_element сам (чтобы взять G и H сумму на счете, а не .pos поле)

1 Ответ

0 голосов
/ 07 февраля 2019

То, что вы пытаетесь достичь, нарушает требование Строгий слабый порядок std::set.В принципе, если у вас есть 2 числа, и ни одно не меньше другого, они должны быть одинаковыми!Они также не могут быть разными (при проверке с использованием другого синтаксиса).

Все ваши операторы сравнения должны определяться согласованно, чтобы было четкое представление о значении для вашего типа.,Какие члены вашего типа являются значительными , т.е. вносят вклад в стоимость?Могут быть и другие члены, но они никогда не должны проверяться в операторах сравнения.

Примером является std::vector.Если два vector s содержат a, b, c, они равны.У них может быть другой объем памяти, оставленный неиспользованным (vector.capacity()), но это не является частью значения любого объекта.

Если у вас есть время, Джон Лакос представил об этом , а Александр Степанов написал об этом .

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