首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++ std::set唯一性覆盖

C++ std::set唯一性覆盖
EN

Stack Overflow用户
提问于 2017-01-04 16:50:50
回答 2查看 2.8K关注 0票数 4

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

我想这么做的原因是,假设我有一个类人,我指定我的人是同一个人,如果他们有相同的名字(甚至生日、地址等)。

ccpreference.com中,他们写了以下内容(对我来说有点不清楚):

标准库在任何地方都使用比较概念,唯一性是通过等价关系来确定的。在不精确的术语中,两个对象a和b被认为是等价的(不是唯一的),如果它们的比较都小于其他对象:!comp(a,b) & !comp(b,a)。

我认为,这个问题也扩展到其他STL容器,甚至算法(甚至整个STL)。因此,如果将来我想使用函数std::find,我将查找person的名称,而不是对象本身。这是正确的吗?

编辑

我想添加一些示例代码。

代码语言:javascript
运行
复制
// My operator overloading comparing two strings.
bool operator==(Node & rhs) const {
        return this->name.compare(rhs.name);
}

然后,在UnitTest中,我向集合中添加两次相同名称的对象。它被添加了两次(但是根据operator==应该是相同的)。

代码语言:javascript
运行
复制
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());
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-04 17:04:02

std::set<T>不使用==进行比较。默认情况下,它比较使用std::less<T>。默认情况下,std::less<T>使用操作符<

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

代码语言:javascript
运行
复制
#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时,可以传递一个比较运算符作为模板参数。在上面的示例中,这可能是比较操作符:

代码语言:javascript
运行
复制
struct Person_Compare {
    bool operator()(const Person& a, const Person& b) const {
        return a.uid < b.uid;
    }
};

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

代码语言:javascript
运行
复制
std::set<Person, Person_Compare> people;

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

票数 3
EN

Stack Overflow用户

发布于 2017-01-04 16:57:33

首先,不要覆盖比较运算符来比较除完全等价之外的任何东西。否则,你就会有一场维护噩梦。

也就是说,你会超越operator <。相反,您应该给set一个比较器类型。

代码语言:javascript
运行
复制
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;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41469176

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档