C++std::设置唯一性覆盖
C++ std::set uniqueness override
std::set<T>
容器如何检查两个对象是否唯一?我尝试重写相等运算符(==),但没有成功。
我想这样做的原因是,我有一个类,比如说Person,我指定我的Person是同一个人,如果他们有相同的名字(甚至可能是出生日期、地址等)。
在ccpreference.com上,他们写了以下内容(我有点不清楚):
无论标准库在哪里使用Compare概念,唯一性都是通过使用等价关系来确定的。用不精确的术语来说,如果两个对象a和b都不是,则认为它们是等价的(不是唯一的)比其他人少:!comp(a,b)&!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;
相关文章:
- 使用ios:ate写入到流会覆盖现有文件
- 我可以重新分配/覆盖std::字符串吗
- 叮叮当当在修复时插入多个"覆盖"说明符
- 谷歌模拟和覆盖关键字
- TMap::Emplace() 在应用现有密钥时会覆盖吗?
- 此测试()中发生了什么意外过程?为什么总是覆盖 ch[0 1 2..]?
- 使用子类覆盖基类中定义的函数
- 当覆盖存在时调用基本虚拟"binded to object"函数
- C++指针在 for 循环中被覆盖
- "main"函数堆栈中的对象在第一个任务运行时被覆盖 (FreeRTOS)
- 为什么我的全局 new() 覆盖被绕过了?
- 被覆盖的函数不会反映在基类中,这是正常行为吗?
- C++找出覆盖同一行的数组
- 专门化模板覆盖函数/避免对象切片
- 重写打印函数而不是覆盖基类
- C++中"覆盖功能的异常规范比基本版本更宽松"的奇怪错误
- 如何在 c++ 中覆盖相同的文本文件
- 覆盖应用程序的低级别键盘挂钩问题
- glBindTexture 是否覆盖活动纹理单元的内容
- C++std::设置唯一性覆盖