【问题标题】:operator< overload for std::set::insert not working as expected运算符 < std::set::insert 的重载未按预期工作
【发布时间】:2021-02-19 23:55:22
【问题描述】:

我正在尝试实现一个std::set::insert,这样它就会“插入”一个结构,因为它还不存在。

我已经为“小于”添加了所需的自定义运算符重载 (&lt;);然而,当代码被执行时,它似乎只是跳过它并且不能按预期工作。 (修改的实现(添加的const noexcept 取自这里:C2676: binary '<': 'const _Ty' does not define this operator or a conversion to a type acceptable to the predefined operator

示例代码:

#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 对象进行更新。

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

【问题讨论】:

标签: c++ set operator-overloading


【解决方案1】:

您对operator&lt; 的实现不符合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);
}

【讨论】:

    【解决方案2】:

    std::set - cppreference.com 说:

    在不精确的术语中,如果两个对象 a 和 b 的比较都不小于另一个,则认为这两个对象是等价的:!comp(a, b) && !comp(b, a)。

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

    常用的实现会是这样的:

    • 如果A.x &lt; B.xA &lt; B 为真
    • A &lt; B 为假(因为B &lt; A 为真)如果A.X &gt; B.x
    • A.x == B.x, A &lt; B iff A.y &lt; B.y
    bool operator< (const Coordinate& obj) const noexcept
    {
        return x < obj.x || (x == obj.x && y < obj.y);
    }
    

    【讨论】:

      【解决方案3】:

      补充解释问题的其他答案:这是该类的 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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-18
        • 2020-11-25
        • 2014-08-07
        相关资源
        最近更新 更多