unique_ptr 向量的取消引用包装器?

Dereference wrapper for vector of unique_ptr?

我最近遇到了这个article;它提供了 boost 的 indirect_iterator 的基本实现,但用于 unique_ptr 迭代器。我决定稍微调整一下文章中的示例,以便我可以将它用于 class 成员之外的向量:

template <typename T>
using SPN = std::unique_ptr<Node<T>>;

template <class BaseIterator>
struct DReferenceIterator : BaseIterator
{
  explicit DReferenceIterator(const BaseIterator & other) : BaseIterator(other) {}
  auto & operator*() const { return *(this->BaseIterator::operator*()); }
  auto * operator->() const { return this->BaseIterator::operator*().get(); }
  auto & operator[](size_t n) const { return *(this->BaseIterator::operator[](n)); }
};

template<typename T>
auto begin_t(std::vector<SPN<T>> & v) 
{
  return DReferenceIterator<typename std::vector<SPN<T>>::iterator>(v.begin());
}

template<typename T>
auto end_t(std::vector<SPN<T>> & v) 
{
  return DReferenceIterator<typename std::vector<SPN<T>>::iterator>(v.end());
}

我可以毫无问题地使用 std::find(begin_t(v), end_t(v), value)。但是,如果我尝试调用 std::sort(begin_t(v), end_t(v)) 它根本不起作用。我确实在 Node<T> class 中提供了 operator<() 的实现,但由于某些原因我的代码无法编译。我得到的编译错误非常广泛且难以阅读,但是,我设法提取了我认为导致问题的内容:

binary =: no operator found which takes a right-hand operand of type std::unique_ptr<Node<float>,std::default_delete<_Ty>> (or there is no acceptable conversion)

此消息是否意味着 std::sort() 正在尝试复制 unique_ptr?在哪种情况下,这是否意味着 DReferenceIterator 包装器没有按预期工作?我是 C++ 的新手,所以如果不是这种情况,请帮助我了解问题到底是什么。

你的 DReferenceIterator 向标准库撒谎,说明它公开了什么。这会导致您在尝试 std::sort 时看到错误。

通过派生自 BaseIterator,您将继承以下内容(除其他外)BaseIterator::value_typeBaseIterator::pointerBaseIterator::reference,它们与 [=24] 不匹配=] 你的 operator 类型。

正确的实现应该更像是

template <class BaseIterator>
struct DReferenceIterator
{
  using value_type = BaseIterator::value_type::element_type;
  using reference = value_type &;
  using pointer = value_type *;
  using difference_type = BaseIterator::difference_type
  using iterator_category = BaseIterator::iterator_category;

  explicit DReferenceIterator(const BaseIterator & other) : other(other) {}

  reference operator*() const { return **other; }
  pointer   operator->() const { return (*other).get(); }
  reference operator[](size_t n) const { return (*other)[n]; }

  DReferenceIterator& operator++() { ++other; return *this; }
  DReferenceIterator& operator--() { --other; return *this; }

  DReferenceIterator& operator+=(difference_type n) { other += n; return *this; }
  DReferenceIterator& operator-=(difference_type n) { other -= n; return *this; }
  difference_type operator-(DReferenceIterator& rhs) { return other - rhs.other; }
  bool operator<(DReferenceIterator& rhs) { return other < rhs.other; }

  // And all the other operators, in terms of those      

private: 
  BaseIterator other;
};