从自定义类型的 std::set 或 std::map 擦除需要 `operator==`?

use*_*026 0 c++ set

当我从std::setstd::map为自定义类型擦除时,例如,info如果我使用https://en.cppreference.com/w/cpp/container/set/erase 中的(3) ,似乎我需要定义一个operator==for info

但是,如果我有指向要删除的对象的迭代器,那么我相信我不需要operator==并且可以使用链接中的 (2)。但是下面的代码似乎可以编译,所以我很困惑

struct info
{
  info(int i, int j, int k) : i{i}, j{j}, k{k} {}
  int i;
  int j;
  int k;

  // bool operator==(const info&rhs)
  // {
  //   return i == rhs.i && j == rhs.j && k == rhs.k;
  // }
};

struct comparer_t
{
  bool operator()(const info &lhs, const info &rhs) const
  {
    if(lhs.i == rhs.i)
    {
      if(lhs.j == rhs.j)
      {
        return lhs.k < rhs.k;
      }

      return lhs.j < rhs.j;
    }

    return lhs.i < rhs.i;
  }
};

int main()
{
  std::set<info, comparer_t> s;
  s.emplace(1,5,6);
  s.erase(info(1,5,6));
  cout << s.size() << endl;
  // cout << (info(1,5,6) == info(1,5,6)) << endl;
}
Run Code Online (Sandbox Code Playgroud)

这会打印出 的大小s0。该erase函数如何知道使用 插入的密钥emplace与我们正在搜索的不带的密钥相同operator==

eer*_*ika 5

看来我需要为custom_class 定义一个运算符==。

你的解释不正确。不需要实现 operator==。

擦除函数如何知道使用 emplace 插入的密钥与我们正在搜索的没有运算符==的密钥相同?

与集合的所有比较都知道顺序的方式相同:它使用提供的比较函数(std::less默认情况下,comparer_t在您的示例中)。如果两个对象的比较都不小于另一个,则认为这些对象是等效的。

PS 在 C++20 中,我建议如下:

struct info
{
    int i;
    int j;
    int k;

    auto operator<=>(const info&) const = default;
};

int main()
{
    std::set<info> s;
    s.emplace(1,5,6);
    s.erase({1,5,6});
}
Run Code Online (Sandbox Code Playgroud)


Nat*_*ica 5

std::set并且std::map不需要operator==运行。set/的比较器map需要提供严格的弱排序,这允许它们仅使用提供的比较器来确定相等性。

让我们假设比较器使用的是像你一样的小于关系。这意味着cmp(a, b)将是trueifa小于b。知道,那么如果cmp(a, b)false,意义a不小于b,如果cmp(b, a)也是false,意义b不小于a,那么两者ab一定是相等的。