【问题标题】:how to trivially adapt set or map ordering predicate for pointers如何轻松地调整指针的集合或映射排序谓词
【发布时间】:2016-10-10 14:04:56
【问题描述】:

这个问题肯定有一个简单的答案...

我有一个 std::set 或一个 std::map 或一些具有自然排序的对象类型 - 比如 std::less。

我需要更改我的集合或地图以包含 shared_ptr 而不是 T 的副本。

所以我想要类似的东西:

using my_set std::set<std::shared_ptr<T>, std::less<*T>>;

但是对于如何指定“在 T 的 ____ 适配器上使用 less 适配器,以便它在取消引用的成员上,而不是在 shared_ptrs 上!”,我画了一个空白!

是否有 std::less&lt;std::dereference&lt;std::shared_ptr&lt;T&gt;&gt;&gt; 等效项?

【问题讨论】:

  • 写一个自定义比较器?
  • 绝对可以做到。我的问题是:没有标准的适配器吗?一定要涨一吨!
  • 不确定,因为比较函数必须采用指针类型T。像std::less&lt;std::dereference&lt;std::shared_ptr&lt;T&gt;&gt;&gt; 这样的东西会期望T
  • 标准库中没有任何东西可以现成使用。您需要编写自己的比较器。

标签: c++ set std shared-ptr


【解决方案1】:

虽然标准库可能尚未提供您需要的内容,但我认为编写自己的 std::dereference_less 非常简单:

#include <memory>
#include <set>

namespace std
{
    template<typename T>
    struct dereference_less
    {
        constexpr bool operator ()(const T& _lhs, const T& _rhs) const
        {
            return *_lhs < *_rhs;
        }
    };
}

int main()
{
   using key_type = std::shared_ptr<int>;
   std::set<key_type, std::dereference_less<key_type>> mySet;
}

Demo(重构了一下,有一个模板类型别名,就像你的问题一样)

【讨论】:

    【解决方案2】:

    C++ 标准库中目前没有仿函数来实现你想要的。您可以编写自定义比较器,或者如果您经常需要此功能,请提供indirect/dereference 函数对象。

    相关且可能有用的线程;第一个为许多运算符提供了一个通用的解决方案(即使它需要一些代码):

    【讨论】:

    • 谢谢。这些看起来很有希望帮助理解这个问题以及为什么 C++ 的这个角落仍然是一个主要的 PIA。
    【解决方案3】:

    由于您已经将内部接口更改为需要取消引用的东西,您也可以只编写一个包装类并提供bool operator&lt; (),如下所示:

    #include <memory>   // shared_ptr
    #include <set>      // set
    #include <iostream> // cout
    using namespace std;
    
    template<typename T>
    class wrapper
    {
    public:
      shared_ptr<T> sp;
    
      bool operator< (const wrapper<T>& rhs) const
      {
        return  *( sp.get() ) < *( rhs.sp.get() ) ;
      }
      wrapper(){}
      wrapper(shared_ptr<T> sp):sp(sp){}
    };
    
    int main()
    {
      shared_ptr<int> sp1 (new int);
      *sp1 = 1;
      shared_ptr<int> sp2 (new int);
      *sp2 = 2;
    
      set<wrapper<int>> S;
      S.insert(wrapper<int>(sp2));
      S.insert(wrapper<int>(sp1));
    
      for (auto& j : S)
        cout << *(j.sp) << endl;
    
      return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 1970-01-01
      • 1970-01-01
      • 2010-09-17
      • 2017-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多