是否有std :: set(或std :: map)的STL比较器,带有shared_ptr键,提供基于值的查找? std :: owner_less到底做了什么?

时间:2016-12-29 07:40:56

标签: c++ c++11 stl shared-ptr comparator

我有std::mapshared_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_lessowner_before(它所称的)究竟是做什么的?他们只是检查底层指针的等价性吗?我不确定我是否正确使用它。

提前感谢您对此问题的任何答案。

1 个答案:

答案 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来查找排序。