【问题标题】:Extracting move only type from std::set从 std::set 中提取仅移动类型
【发布时间】:2017-12-15 07:16:01
【问题描述】:

我有一个std::set<std::unique_ptr<T>>,我想把它移到std::vector<std::unique_ptr<T>>

#include <set>
#include <vector>
#include <memory>

class C {};

int main()
{
  std::set<std::unique_ptr<const C>> s;
  std::vector<std::unique_ptr<const C>> v;
  std::move(s.begin(), s.end(), std::back_inserter(v));
}

这在 VS2017 上会出现以下错误:

错误 C2280: 'std::unique_ptr>::unique_ptr(const std::unique_ptr<_ty>> &)': 试图引用已删除的函数

我们不能将迭代器从std::set 移动到非常量变量吗?有什么可行的解决方案来解决这个问题?

【问题讨论】:

    标签: c++ c++11 stl set move


    【解决方案1】:

    为了从集合中提取只能移动的元素,唯一的可能是使用 C++17 中添加的 extract 方法:

    while (!s.empty())
        v.emplace_back(std::move(s.extract(s.begin()).value()));
    

    如果您不能使用 C++17,则允许修改集合中的元素(例如使用 mutable只有在您确保它在强制排序中保持相同位置时才允许- 也就是说,只要它在您的比较器下与该集合的所有其他成员相比具有相同的结果。您可以通过提供一个比较器来做到这一点,该比较器在非空之前排序空唯一指针(请注意,标准不保证这一点)并在修改后立即擦除修改过的元素:

    template<class T> struct MutableWrapper { mutable T value; };
    template<class T> struct MutableWrapperCompare {
      bool operator()(MutableWrapper<T> const& lhs, MutableWrapper<T> const& rhs) {
        return lhs.value && rhs.value ? lhs.value < rhs.value : rhs.value;
      }
    };
    
    int main()
    {
      std::set<MutableWrapper<std::unique_ptr<const C>>, MutableWrapperCompare<std::unique_ptr<const C>>> s;
      std::vector<std::unique_ptr<const C>> v;
      while (!s.empty())
      {
        v.emplace_back(std::move(s.begin()->value));
        s.erase(s.begin());
      }
    }
    

    然而,这相当丑陋和危险;您最好使用来自Boost.Containerboost::container::set,它具有C++ 17 提取方法(since 1.62.0;它was undocumented,但这只是一个疏忽,请注意相应的extract 方法已记录为mapmultimap)。

    【讨论】:

    • 那么在我使用的编译器实现它之前,我是否可以为我的源代码库实现这个方法?
    • @tunc 有点像,但它很丑 - 见上文。如果可能的话,我会推荐使用 Boost (boost::container::set, v 1.62.0 及更高版本)。
    • merge 方法怎么样?
    • @v.oddou: merge 也是 C++17
    • 还有另一种方法described here,危险性小一些,但仍然不理想。
    猜你喜欢
    • 2019-04-01
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-16
    • 2011-06-16
    • 2018-12-20
    • 2012-04-14
    相关资源
    最近更新 更多