如何将std :: unique_ptr <>从一个STL容器移动到另一个容器?

kfm*_*e04 4 c++ stl c++11

问题

我有一个模板容器MyContainer<std::unique_ptr<Foo>>,它有一个std::deque<T>和一个std::vector<T>成员.

在内部方法中,如果谓词的计算结果为true send_to_purgatory_if( predicate ),我想查看所有项目m_taskdq并将项目移动到.m_taskdqm_purgatory

问题

我有两个问题,我正在努力:

  • it如果我从循环内部删除m_taskdq中的项目,我的迭代器会被删除
  • 我担心std::unique_ptr<>如果我分两步进行移动的状态(问题第1行和第2行 - 第2行,我认为std::unique_ptr<>指向的it是未定义的?)

我该如何修复此代码?

    template <typename T>
    class MyContainer
    {
      typedef std::function<bool(T&)>  PREDICATE;

      void send_to_purgatory_if( PREDICATE p )
      {
// bad code -------------------------------------
        for( auto it=m_taskdq.begin(); it!=m_taskdq.end(); ++it )
        {
          if ( p( *it ) )
          {
            m_purgatory.emplace_back( move( *it ));  // problem line 1
            m_taskdq.erase( it );                    // problem line 2
          }
        }
// end bad code ---------------------------------
      }

      std::deque<  T >  m_taskdq;                                                     
      std::vector< T >  m_purgatory;
    };
Run Code Online (Sandbox Code Playgroud)

How*_*ant 13

这实际上是一个C++ 98问题,带有关于移动语义的红鲱鱼.首先要问的是如何在C++ 98中执行此操作:

std::deque::erase(iterator)返回一个iterator引用擦除后的元素.所以先做到最好:

 void send_to_purgatory_if( PREDICATE p )
  {
    for( auto it=m_taskdq.begin(); it!=m_taskdq.end();)
    {
      if ( p( *it ) )
      {
        m_purgatory.emplace_back(*it);
        it = m_taskdq.erase(it);
      }
      else
        ++it;
    }
  }
Run Code Online (Sandbox Code Playgroud)

现在很容易使它与C++ 11移动语义一起使用:

 void send_to_purgatory_if( PREDICATE p )
  {
    for( auto it=m_taskdq.begin(); it!=m_taskdq.end();)
    {
      if ( p( *it ) )
      {
        m_purgatory.emplace_back(std::move(*it));
        it = m_taskdq.erase(it);
      }
      else
        ++it;
    }
  }
Run Code Online (Sandbox Code Playgroud)

unique_ptr从移动taskdq成为空unique_ptremplace_back,然后它就会在下一行删除.没有伤害,没有犯规.

当有一个时erase,返回erase就可以很好地增加迭代器.当没有时erase,正常的迭代器增量是有序的.