我有std::map
个shared_ptr<T>
个密钥,我需要它来使用实际值(T
类型,即*key
)用于查找,而不是共享指针本身的值。
我知道我可以编写自己的自定义比较器(正如我在下面所做的那样),但我想知道STL是否提供专门用于此目的的比较器。
为了演示我正在谈论的内容,我创建了一个使用std::set
字符串的简单示例(我还将其设为on GitHub as a gist):
#include <set>
#include <string>
#include <memory>
#include <iostream>
#include <functional>
template< typename T >
struct shared_ptr_comparator {
bool operator()(const std::shared_ptr<T> &a, const std::shared_ptr<T> &b) const {
return std::less<T>()(*a, *b);
}
};
void ptr_set_with_custom_comparator() {
std::set< std::shared_ptr<std::string>, shared_ptr_comparator<std::string> > ptr_set;
ptr_set.insert(std::make_shared<std::string>("world"));
ptr_set.insert(std::make_shared<std::string>("hello"));
ptr_set.insert(std::make_shared<std::string>("abc"));
for(auto const& entry : ptr_set) {
std::cout << *entry << std::endl;
}
}
void ptr_set_with_owner_less() {
std::set< std::shared_ptr<std::string>, std::owner_less<std::shared_ptr<std::string>> > ptr_set;
ptr_set.insert(std::make_shared<std::string>("world"));
ptr_set.insert(std::make_shared<std::string>("hello"));
ptr_set.insert(std::make_shared<std::string>("abc"));
for(auto const& entry : ptr_set) {
std::cout << *entry << std::endl;
}
}
void raw_set() {
std::set<std::string> raw_set;
raw_set.insert("world");
raw_set.insert("hello");
raw_set.insert("abc");
for(auto const& entry : raw_set) {
std::cout << entry << std::endl;
}
}
int main() {
std::cout << "A basic set of strings:" << std::endl;
raw_set();
std::cout << std::endl;
std::cout << "A set of shared_ptr<string>s with owner_less as the comparator:" << std::endl;
ptr_set_with_owner_less();
std::cout << std::endl;
std::cout << "A set of shared_ptr<string>s with the comparator shared_ptr_comparator:" << std::endl;
ptr_set_with_custom_comparator();
return 0;
}
上面的代码可以遵守clang++ -Wall -std=c++11
。这是输出:
A basic set of strings:
abc
hello
world
A set of shared_ptr<string>s with owner_less as the comparator:
world
hello
abc
A set of shared_ptr<string>s with the comparator shared_ptr_comparator:
abc
hello
world
这里,迭代和打印内容std::set
时的排序顺序意味着正在比较_actual底层值)。以上示例的快速概述:
函数raw_set
仅使用set<string>
(不使用shared_ptr
),并且可供参考。
我能用手写的shared_ptr_comparator
来实现我的目标。使用它的函数ptr_set_with_custom_comparator
按预期工作。
函数ptr_set_with_owner_less
未按预期工作。 owner_less
(或owner_before
)是否依赖于指针本身的地址/值?
我有两个问题:
STL中是否存在等同于shared_ptr_comparator
(在上面的程序中定义)的任何内容?我问,因为我写的比较器似乎是一个非常常见的用例,如果STL没有相应的东西,我会非常惊讶。
owner_less和owner_before(它所称的)究竟是做什么的?他们只是检查底层指针的等价性吗?我不确定我是否正确使用它。
提前感谢您对此问题的任何答案。
答案 0 :(得分:3)
STL中是否存在等同于shared_ptr_comparator(在上面的程序中定义)的任何内容?我问,因为我写的比较器似乎是一个非常常见的用例,如果STL没有任何与之相当的东西,我会非常惊讶。
我也很惊讶,但是不,STL没有内置的指针比较器可以这样工作。然而,有更好的方法来实现它允许传递任何指针。
template<typename T, typename comp_t>
bool ptr_compare(T lhs, T rhs, comp_t comp) {
return comp(*lhs, *rhs);
}
你可以这样称呼它:
ptr_compare(a_ptr, b_ptr, std::less<int>())
如果你想要一个与STL容器兼容的版本:
template<typename T>
bool ptr_less(T lhs, T rhs) {
return std::less<decltype(*lhs)>()(*lhs, *rhs);
}
owner_less和owner_before(它调用的)究竟做了什么?他们只是检查底层指针的等价性吗?我不确定我是否正确使用它。
std::owner_less
不按价值进行比较,而是按所有者进行比较,因此与您的问题无关。
std::shared_ptr<T>::owner_before
调用{p> std::owner_less
来查找排序。