从自定义类型的std::set或std::map擦除需要`operator==`?
当我从std::set或std::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;
}
这会打印出 的大小s是0。该erase函数如何知道使用 插入的密钥emplace与我们正在搜索的不带的密钥相同operator==?
回答
看来我需要为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});
}
回答
std::set并且std::map不需要operator==运行。set/的比较器map需要提供严格的弱排序,这允许它们仅使用提供的比较器来确定相等性。
让我们假设比较器使用的是像你一样的小于关系。这意味着cmp(a, b)将是trueifa小于b。知道,那么如果cmp(a, b)是false,意义a不小于b,如果cmp(b, a)也是false,意义b不小于a,那么两者a和b一定是相等的。
THE END
二维码