gpt4 book ai didi

c++ - 使用 operator== 时 std::set 中 unique_ptr 的深度比较

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:27:18 27 4
gpt4 key购买 nike

我正在尝试使用 std::set 将一组 unique_ptr 保存到我定义的自定义对象中。我在定义集合时提供了一个自定义比较函数(以启用深度比较)。在将元素插入集合时,此比较功能似乎可以正常工作,即具有相同内容的项目不会被插入两次。

但是,如果我使用 operator== 比较两个集合,它似乎会被忽略,即具有等效元素的集合返回为不相等,而我期望(希望)它相等(因为我提供的自定义比较功能会进行深度比较)。

compare函数是否只在插入时使用?如果是这样,是否有替代方法让 operator== 进行深度比较?

感谢任何指点。谢谢:)

示例代码

//
// main.cpp
// Test

#include <iostream>
#include <set>

class Person {
private:
std::string mName;

public:
Person(const std::string& name);
virtual ~Person() {}

void setName(std::string& name);
std::string getName();
};

typedef std::unique_ptr<Person> PersonUniquePtr;

Person::Person(const std::string& name)
: mName{ name }
{
}

void Person::setName(std::string& name)
{
mName = name;
}

std::string Person::getName()
{
return mName;
}

bool isLess(Person* p1, Person* p2)
{
if (p1->getName().compare(p2->getName()) == -1)
return true;

return false;
}

struct PersonUniquePtr_less {
bool operator()(PersonUniquePtr const& p1, PersonUniquePtr const& p2) const
{
return isLess(p1.get(), p2.get());
}
};

int main(int argc, const char* argv[])
{
std::set<PersonUniquePtr, PersonUniquePtr_less> personSet1;
std::set<PersonUniquePtr, PersonUniquePtr_less> personSet2;

PersonUniquePtr person1 = std::make_unique<Person>("Adam");
PersonUniquePtr person2 = std::make_unique<Person>("Adam");
personSet1.insert(std::move(person1));
personSet1.insert(std::move(person2));
std::cout << "personSet1.size(): " << personSet1.size() << std::endl; //Expected 1

PersonUniquePtr person3 = std::make_unique<Person>("Bruce");
personSet1.insert(std::move(person3));
std::cout << "personSet1.size(): " << personSet1.size() << std::endl; //Expected 2

PersonUniquePtr person4 = std::make_unique<Person>("Adam");
PersonUniquePtr person5 = std::make_unique<Person>("Bruce");
personSet2.insert(std::move(person4));
personSet2.insert(std::move(person5));
std::cout << "personSet2.size(): " << personSet2.size() << std::endl; //Expected 2

std::cout << "PersonSet1:" << std::endl;
for (auto& person : personSet1) {
std::cout << person->getName() << std::endl;
} //Prints out Adam Bruce

std::cout << "PersonSet2:" << std::endl;
for (auto& person : personSet2) {
std::cout << person->getName() << std::endl;
} //Prints out Adam Bruce

bool setsAreEqual = (personSet1 == personSet2);
if (setsAreEqual) {
std::cout << "Sets are equal" << std::endl;
} else {
std::cout << "Sets are not equal" << std::endl;
}

return 0;
}

最佳答案

C++11 容器要求说 a == b 等价于

distance(a.begin(), a.end()) == distance(b.begin(), b.end())
&& equal(a.begin(), a.end(), b.begin())

std::equal 不使用您的自定义比较,它使用operator==

您可以通过使用自定义谓词调用 std::equal 自行执行比较:

a.size() == b.size()
&& std::equal(a.begin(), a.end(), b.begin(),
[](PersonUniquePtr const& p1, PersonUniquePtr const& p2) {
PersonUniquePtr_less cmp;
return !cmp(p1, p2) && !cmp(p2, p1);
});

在 C++14 中它更简单,因为有一个新的 std::equal 重载采用四个迭代器,尽管正如 TemplateRex 在下面的评论中指出的那样,这比测试 效率低a.size() == b.size() 手动:

std::equal(a.begin(), a.end(), b.begin(), b.end(),
[](PersonUniquePtr const& p1, PersonUniquePtr const& p2) {
PersonUniquePtr_less cmp;
return !cmp(p1, p2) && !cmp(p2, p1);
});

在 C++14 中,您可以使用多态 lambda 来节省一些输入:

std::equal(a.begin(), a.end(), b.begin(), b.end(),
[](auto const& p1, auto const& p2) {
PersonUniquePtr_less cmp;
return !cmp(p1, p2) && !cmp(p2, p1);
});

关于c++ - 使用 operator== 时 std::set 中 unique_ptr 的深度比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25550342/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com