2016-08-08 7 views
1

std :: remove_ifは、(イテレータの順序に従って)各要素の述語を常に呼び出すか、順不同で呼び出すことができますか?std :: remove_ifは述語を順番に呼び出すことが保証されていますか?

void processVector(std::vector<int> values) 
{ 
    values.erase(std::remove_if(values.begin(), values.end(), [](int v) 
    { 
     if (v % 2 == 0) 
     { 
      std::cout << v << "\n"; 
      return true; 
     } 
     return false; 
    })); 
} 

私が処理し、一定の基準を満たすベクトルのすべての要素を削除し、消去+ remove_ifは、そのための完璧なようだする必要があります。ここでは

は私がやりたいもののおもちゃの一例です。しかし、私が行う処理には副作用があり、処理が順番に行われるようにする必要があります(おもちゃの例では、値を元のベクトルの順序で印刷したいと仮定します)。

私の述語が各項目に対して順番に呼び出されると想定するのは安全でしょうか?

私は、C++ 17の実行ポリシーがこれを曖昧にしていると思いますが、C++ 17はまだ出ていないので、明らかに私を助けません。

編集:これは良い考えですか?または、これを達成するためのより良い方法がありますか?

+0

明らかに、副作用は 'ベクター'自体を変更するでしょうか?それはどんなイベントでも使用されているイテレータを無効にするので、最初にそのイテレータを使用することをお勧めします。 'remove_if'の実行中に、' vector'中の任意の項目の正確な位置が保証されていないので、 'vector'の_values_に影響を与える副作用にも注意してください。 – ShadowRanger

+0

いいえ、副作用によってベクターが変更されることはありません。副作用は実際にファイルにいくつかのことを書いています。 – Solaraeus

+0

天気かどうかは疑問だと思います。副作用のすべてを行い、その後削除します。 –

答えて

7

標準では、述語の呼び出し順序を保証していません。

あなたが使用すべきものはstable_partitionです。あなたの述語に基づいてシーケンスを分割します。 stable_partitionは、両方のデータセットの相対的な順序が保証されているため、パーティション化されたシーケンスを歩き回り、 "副作用"を実行することができます。次に、vectorから要素を消去することができます。

stable_partitionここでは、erase_ifは「消去済み」要素の内容を未定義にしているため、ここで使用する必要があります。コードで

void processVector(std::vector<int> values) 
{ 
    auto it = std::stable_partition(begin(values), end(values), [](int v) {return v % 2 != 0;}); 

    std::for_each(it, end(values), [](int v) {std::cout << v << "\n";}); 

    values.erase(it, end(values)); 
} 
+0

ええ、私は自分自身をダブルチェックして、そのコメントを削除するように質問を再読しました。まだ:単に 'erase_if'を実行し、その後に' for_each'を続けるのはなぜですか? –

+0

@MooingDuck: 'erase_if'は、範囲の末尾にある"空 "のスロットに*何も移動することを保証しないためです。 'stable_partition'が行います。 –

-1

彼らは順序で処理されなければならないが、それはを保証ではありません。

std::remove_if() "removed"アイテムをコンテナの最後に移動しますが、実際にはerase()が呼び出されるまでコンテナから削除されません。どちらの操作も、std::vectorの既存のイテレータを無効にする可能性があります。

+4

標準ではインオーダ処理が保証されていますか? –

+0

@DafangCao:そうです。私の悪い。'消去 'は、より簡単なアルゴリズムを使用できるようにする第2の「パーティション」には何も保証されないことを忘れています。 –

+0

@NicolBolas:順番に処理されることを保証されているとは言わなかったが、私はそれを順番に処理すべきだと言った(「cppreference.com」の「実現可能な実装」(http://en.cppreference .com/w/cpp/algorithm/remove))。しかし、標準では、§25.3.8の「remove_if()」のためにこれを述べています: "*複雑さ:対応する述語の正確に最後のアプリケーション。*"したがって、述語に項目を渡すことはできません。一度(ソートできるように)。しかし、私は、後者が可能性は高いものの、最初から最後までではなく、最後から最初へのアルゴリズムの動作を妨げないと思います。 –

関連する問題