std::set 已经包含该成员,即使它不同

3 c++ set

我写了以下简单的代码:

std::set<Edge> edges;
Edge edge1("a","b");
Edge edge2("a","c");
edges.insert(edge1);
if (edges.find(edge2) != edges.end()) //edge2 already exists
    std::cout << "OH NO!";
Run Code Online (Sandbox Code Playgroud)

这有一个错误,因为哦不!即使被打印edge1并且edge2彼此不同。

以下是我已经实现operator ==operator <Edge

bool operator==(const Edge &e1, const Edge &e2) {
    return (e1.source == e2.source) && (e1.destination == e2.destination);
}

bool operator<(const Edge &e1, const Edge &e2) {
    return e1.source < e2.source;
}
Run Code Online (Sandbox Code Playgroud)

是什么导致了这个错误?

Joh*_*eau 6

根据你的operator<,Edge("a","b")Edge("a","c")是相等的。当第一个元素相同时,您需要告诉计算机您希望如何对项目进行排序。最简单的方法是进行字典排序。std::tie非常适合这个。

你需要#include <tuple>为此。

bool operator<(const Edge &e1, const Edge &e2) {
    return std::tie(e1.source, e1.destination) < std::tie(e2.source, e2.destination);
}
Run Code Online (Sandbox Code Playgroud)

编辑: Nah 不要根据operator<它是否足够简单来定义其他运算符。

或者做。由你决定。我不确定我更喜欢哪种风格。

bool operator==(const Edge &e1, const Edge &e2) {
    return e1.source == e2.source && e1.destination == e2.destination;
}
Run Code Online (Sandbox Code Playgroud)

是完全可读和可维护的。也许如果它更复杂,我会根据operator<.


旧建议如下:

还建议根据以下内容定义所有其他比较函数operator<

bool operator==(const Edge &e1, const Edge &e2) {
    return !(e1 < e2) && !(e2 < e1);
}
Run Code Online (Sandbox Code Playgroud)

不一定是最有效的(取决于您的编译器),但除非您绝对需要它尽可能快,否则这可以使您的代码保持超级可维护性。