Jo *_*tes 40 c++ unique-ptr c++11 c++14
我经常发现自己想写这样的代码:
class MyClass
{
public:
  void addObject(std::unique_ptr<Object>&& newObject);
  void removeObject(const Object* target);
private:
  std::set<std::unique_ptr<Object>> objects;
};
但是,很多std :: set接口对std :: unique_ptrs都没用,因为查找函数需要std :: unique_ptr参数(我显然没有这些参数,因为它们由集合本身拥有).
我可以想到两个主要的解决方案.
创建临时unique_ptr以进行查找.例如,上面的removeObject()可以实现如下:
void MyClass::removeObject(const Object* target)
{
  std::unique_ptr<Object> targetSmartPtr(target);
  objects.erase(targetSmartPtr);
  targetSmartPtr.release();
}
将原始指针映射替换为unique_ptrs.
  // ...
  std::map<const Object*, std::unique_ptr<Object>> objects;
};
然而,对我来说,两者似乎都有点愚蠢.在解决方案1中,erase()不是noexcept,因此临时unique_ptr可能会删除它实际上不拥有的对象,而2需要不必要地为容器存储两倍.
我知道Boost的指针容器,但与现代C++ 11标准库容器相比,它们目前的功能有限.
我最近在阅读有关C++ 14的内容,并且遇到了"将异构比较查找添加到关联容器".但是形成我对它的理解,查找类型必须与键类型相当,但原始指针不能与unique_ptrs相比.
任何人都知道更优雅的解决方案或即将添加的C++解决了这个问题?
Yak*_*ont 32
在C++ 14中,如果存在std::set<Key>::find则是一个template函数Compare::is_transparent.传入的类型不需要Key,在比较器下等效.
所以写一个比较器:
template<class T>
struct pointer_comp {
  typedef std::true_type is_transparent;
  // helper does some magic in order to reduce the number of
  // pairs of types we need to know how to compare: it turns
  // everything into a pointer, and then uses `std::less<T*>`
  // to do the comparison:
  struct helper {
    T* ptr;
    helper():ptr(nullptr) {}
    helper(helper const&) = default;
    helper(T* p):ptr(p) {}
    template<class U, class...Ts>
    helper( std::shared_ptr<U,Ts...> const& sp ):ptr(sp.get()) {}
    template<class U, class...Ts>
    helper( std::unique_ptr<U, Ts...> const& up ):ptr(up.get()) {}
    // && optional: enforces rvalue use only
    bool operator<( helper o ) const {
      return std::less<T*>()( ptr, o.ptr );
    }
  };
  // without helper, we would need 2^n different overloads, where
  // n is the number of types we want to support (so, 8 with
  // raw pointers, unique pointers, and shared pointers).  That
  // seems silly:
  // && helps enforce rvalue use only
  bool operator()( helper const&& lhs, helper const&& rhs ) const {
    return lhs < rhs;
  }
};
然后使用它:
typedef std::set< std::unique_ptr<Foo>, pointer_comp<Foo> > owning_foo_set;
现在,owning_foo_set::find将接受unique_ptr<Foo>或Foo*或shared_ptr<Foo>(或任何派生类Foo)并找到正确的元素.
在C++ 14之外,你被迫使用mapto unique_ptr方法或类似的东西,因为签名find过于严格.或者写自己的set等价物.
| 归档时间: | 
 | 
| 查看次数: | 3996 次 | 
| 最近记录: |