std :: set使用运算符<

时间:2019-02-07 20:35:26

标签: c++ stl set operator-overloading

这个问题有点和我在这里的其他问题有关:link(请参阅评论中的讨论)。基本上,我有以下问题:

我有一个node班。其中包含一些最重要的字段:GHpospos是Qt的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==)。节点之一被认为不是唯一的,因为cuz std::set使用operator<来比较其元素。因此n1n3具有相同的G+H值,它们被认为是相等的(输出第二行中的2是set的元素数-> 2,而不是3)。

在我知道std::set使用operator<进行相等性比较之前,我写过operator==operator!=认为该集合将使用其中的一个比较我班上的对象。但是它使用operator<

所以我的问题是为什么它实际上使用此运算符。使用operator==operator!=会更容易吗?

对我来说,这有点复杂,因为我必须考虑另一种写operator<或使用其他容器(因此编写lambda)的方法,或者我可以使用.pos在{{ 1}}并自己重写operator<(在帐户中获取std::min_elementG的总和,而不是H字段)

1 个答案:

答案 0 :(得分:1)

您试图实现的目标违反了std::set的{​​{3}}要求。基本上,如果您有2个数字,且两个数字都不小于另一个,则它们必须相同!它们也不能不同(当使用某些不同的语法检查时)。

应该对所有比较运算符进行统一定义,以便为您的类型明确定义 value 。您类型中的哪些成员是“ 显着”,即对价值有所贡献?可能还有其他成员,但是绝对不要在比较运算符中对其进行检查。

一个示例是std::vector。如果两个vector都包含a, b, c,则它们相等。它们可能有不同数量的未使用存储空间(vector.capacity()),但这不是任何一个对象的 value 的一部分。

如果有时间,请Strict Weak OrderingJohn Lakos has presented about this