std::set::insert 的运算符< 重载未按预期工作

operator< overload for std::set::insert not working as expected

我正在尝试实现一个 std::set::insert,这样它将 'insert' 一个结构,因为它还不存在。

我已经为 'less than' 添加了所需的自定义运算符重载 (<);然而,当代码被执行时,它似乎只是跳过它而没有按预期工作。 (修改的实现(const noexcept 的添加取自此处:

示例代码:

#include <set>

struct Coordinate
{
int x;
int y;

Coordinate(int x = 0, int y = 0) : x(x), y(y)
{
}

bool operator==(const Coordinate& obj)
{
    return x == obj.x && y == obj.y;
}

bool operator!=(const Coordinate& obj)
{
    return x != obj.x && y != obj.y;
}

bool operator< (const Coordinate& obj) const noexcept
{
    return x < obj.x && y < obj.y;
}
};

int main(){
std::set<Coordinate> current_set = {Coordinate(1, 2)};

Coordinate new_coordinate(1, 3);

current_set.insert(new_coordinate);
}

需要明确的是,通过此实现,即使成员明显不同,集合也不会使用 new_coordinate 对象进行更新。

如有任何帮助,我们将不胜感激。

您对 operator< 的实施对于 std::set 的目的是不正确的。不符合strictly weak ordering.

的要求

改为:

bool operator<(const Coordinate& obj) const noexcept
{
    if ( x != obj.x )
    {
       return x < obj.x;
    }
    return y < obj.y;
}

您可以使用 std::tie 来简化它。

bool operator<(const Coordinate& obj) const noexcept
{
    return std::tie(x, y) < std::tie(obj.x, obj.y);
}

std::set - cppreference.com 说:

In imprecise terms, two objects a and b are considered equivalent if neither compares less than the other: !comp(a, b) && !comp(b, a).

Coordinate(1, 2)Coordinate(1, 3)两个对象的成员x都是1,所以operator<不可能为真,因此认为它们相同。

常用的实现是这样的:

  • A < B 如果 A.x < B.x
  • 为真
  • A < B 为假(因为 B < A 为真)如果 A.X > B.x
  • A.x == B.xA < B 当且仅当 A.y < B.y
bool operator< (const Coordinate& obj) const noexcept
{
    return x < obj.x || (x == obj.x && y < obj.y);
}

补充解释问题的其他答案:这是 class:

的 C++20 版本
struct Coordinate
{
    int x;
    int y;
    
    friend auto
    operator<=>(const Coordinate&, const Coordinate&) = default;
};

int main()
{
    std::set<Coordinate> current_set = {{1, 2}};
    current_set.emplace(1, 3);
}