C++std::设置唯一性覆盖

C++ std::set uniqueness override

本文关键字:覆盖 唯一性 设置 C++std      更新时间:2023-10-16

std::set<T>容器如何检查两个对象是否唯一?我尝试重写相等运算符(==),但没有成功。

我想这样做的原因是,我有一个类,比如说Person,我指定我的Person是同一个人,如果他们有相同的名字(甚至可能是出生日期、地址等)。

在ccpreference.com上,他们写了以下内容(我有点不清楚):

无论标准库在哪里使用Compare概念,唯一性都是通过使用等价关系来确定的。用不精确的术语来说,如果两个对象a和b都不是,则认为它们是等价的(不是唯一的)比其他人少:!comp(a,b)&amp!comp(b,a)。

我假设,这个问题也扩展到其他STL容器,甚至算法(甚至可能扩展到整个STL)。所以,如果将来我想使用函数std::find,我会查找人名,而不是对象本身。这是正确的吗?


编辑

我想添加一些示例代码。

// My operator overloading comparing two strings.
bool operator==(Node & rhs) const {
return this->name.compare(rhs.name);
}

然后,在UnitTest中,我将两次具有相同名称的对象添加到集合中。它被添加两次(但根据operator==.应相同

void test_adding_two_identical_nodes() {
// The pool is a set<Node> inside
model::Node_Pool pool{};
pool.store_node(model::Node{"Peter"});
pool.store_node(model::Node{"Peter"});
// Should be only 1 because the same node should be added once into a set.
ASSERT_EQUAL(1, pool.size());
}

std::set<T>不使用==进行比较。默认情况下,它使用std::less<T>进行比较。反过来,默认情况下,std::less<T>使用运算符<

实现集合的一种方法是覆盖operator<,如下所示:

#include <set>
#include <cassert>
struct Person {
const char *name;
int uid;
};
bool operator<(const Person& a, const Person& b) {
return a.uid < b.uid;
}
int main () {
Person joe = {"joseph", 1};
Person bob = {"robert", 2};
Person rob = {"robert", 3};
Person sue = {"susan", 4};
std::set<Person> people;
people.insert(joe);
people.insert(bob);
people.insert(rob);
assert(people.count(joe) == 1);
assert(people.count(bob) == 1);
assert(people.count(rob) == 1);
assert(people.count(sue) == 0);
Person anonymous_3 = {"", 3};
assert( std::strcmp(people.find(anonymous_3)->name, "robert") == 0);
}

或者,在声明set时,可以传递一个比较运算符作为模板参数。在上面的例子中,这可能是比较运算符:

struct Person_Compare {
bool operator()(const Person& a, const Person& b) const {
return a.uid < b.uid;
}
};

std::set声明可能如下所示:

std::set<Person, Person_Compare> people;

示例的其余部分保持不变。

首先,不要重写比较运算符来比较除TOTAL等价之外的任何内容。否则,您将陷入维护噩梦。

也就是说,您将覆盖operator <。不过,您应该给set一个比较器类型。

struct compare_people : std::binary_function<person,person,bool>
{
bool operator () ( person const& a, person const& b) const { return a.name() < b.name();
};
std::set<person, compare_people> my_set;