【问题标题】:Is there an STL comparator for std::set (or std::map) with shared_ptr keys that provides value-based lookups? What exactly does std::owner_less do?是否有用于 std::set (或 std::map )的 STL 比较器,带有提供基于值的查找的 shared_ptr 键? std::owner_less 究竟是做什么的?
【发布时间】:2017-05-13 12:21:31
【问题描述】:

我有一个带有shared_ptr<T> 键的std::map,我需要它使用实际值(类型为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&lt;string&gt;(不使用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(它所调用的)究竟是做什么的?他们只是检查底层指针的等价性吗?我不确定我是否正确使用它。

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

【问题讨论】:

  • 您是否仔细阅读了标准C++ containers的相关文档?

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


【解决方案1】:

在 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&lt;T&gt;::owner_beforestd::owner_less 调用以找出排序。

【讨论】:

  • 谢谢!简单说明一下:ptr_compare 是一个很好的概括,但我认为它不能用作 STL 容器比较器,因为他们希望函子只接受两个参数(lhsrhs)。您可以避开上面的 comp_t comp,它可以与 STL 容器一起使用。
  • 对,我编辑了答案并添加了适用于 STL 容器的示例 ptr_less。
  • 只是好奇,owner_less 的用例到底是什么?而且,它的排序依据是什么? (是否按指针地址的数值排序?)
  • @ArjunMenon Here's 很好的解释。
猜你喜欢
  • 1970-01-01
  • 2013-03-20
  • 2017-07-28
  • 1970-01-01
  • 2014-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多