1

std::shared_ptr<MotionTask>時々クレンジングする必要があるオブジェクトのベクトルがあります。

// this assert passes
assert(std::all_of(d_tasks.begin(), d_tasks.end(),
       [](shared_ptr<MotionTask> task) { return bool(task); }));

// Remove any committed tasks for which the corresponding module has completed
d_tasks.erase(
  remove_if(
    d_tasks.begin(), 
    d_tasks.end(),
    [module](shared_ptr<MotionTask> const& task)
    {
      return task->isCommitted() && task->getModule() == module;
    }
  )
);

// this assert fails
assert(std::all_of(d_tasks.begin(), d_tasks.end(),
       [](shared_ptr<MotionTask> task) { return bool(task); }));

assertタスクのベクトル内で 1 つが null (false) であるため、ファイナルは失敗しています。

eraseへの呼び出しがメンバーを無効にする方法がわかりません。単体テストでこれを再現できませんでした。

上記のコードからわかる説明はありますか? そうでない場合、これをデバッグするにはどうすればよいですか?

4

2 に答える 2

7

単一の反復子のstd::vector::eraseオーバーロードを呼び出しています。2 つの反復子バージョンが必要です。

d_tasks.erase(
  remove_if(
    d_tasks.begin(), 
    d_tasks.end(),
    [module](shared_ptr<MotionTask> const& task)
    {
      return task->isCommitted() && task->getModule() == module;
    }
  ),
  d_tasks.end() // HERE!!
);

単一反復子バージョンは単一要素を削除しますが、消去削除イディオムでは範囲を削除する必要があります。これは、2 つの反復子バージョンを使用して実現されます。

于 2013-06-09T23:25:22.657 に答える
2

問題は、vector<T>::erase1 つの要素を消去する の単一反復子バージョンを使用していることです。

これを修正するには、2 つの方法があります。1 つ目は、 の 2 つの反復子バージョンを使用することですvector<T>::erase。2 つ目は、イテレータ ベースのアルゴリズムを使用せず、コンテナ ベースのアルゴリズムの記述を開始することです。

template<typename Container, typename Lambda>
Container&& remove_if_erase( Container&& container, Lambda&& closure ) {
  using std::begin; using std::end;
  container.erase(
    std::remove_if(
      begin(container), end(container), std::forward<Lambda>(closure)
    ),
    end(container)
  );
  return std::forward<Container>(container);
}

これは、要素の削除と消去の 2 つの操作を 1 回のパスで行います。これが だけでなく、や などvectorの連想コンテナでも機能するように、特性クラスを作成できます。setmap

私が便利だと思う同様のものsort_unique_eraseは、コレクションを取得して重複を削除する です。

このようなコンテナベースのアルゴリズムを記述することで、コードがより明確になり、エラーが発生しにくくなります。多くの反復子ベースの手法は、単純なタイプミスで予期しない方法で静かに失敗します。テスト済みのコンテナー ベースのアルゴリズムは、渡されたコンテナーで確実に動作するか、コンパイルに失敗します。

于 2013-06-09T23:38:08.687 に答える