1

ラムダを使用して述語を渡す際に問題が発生しました。述語に一致する要素を 2 番目のコンテナーの先頭に移動しようとしていますが、うまくいかなかったようです。何が問題なのですか?

#include <iostream>
#include <vector>
#include <list>
#include <iterator>
#include <utility>
#include <algorithm>


using namespace std;

    template <typename iterator, typename Container, typename T>
    void move_if(iterator b, iterator e, Container o, T pred)
    {
        if(pred)
        {
            o.insert(o.begin(),pred);
        }

    }


    int main()
    {
        vector<int>v{1,2,3,4,5,6,7,8,9,10};
        vector<int>v2;
        for (auto i=v.begin(); i !=v.end(); ++i)
            save_if(v.begin(), v.end(), v2, []( vector<int>::iterator i){return (*i>5);});

        return 0;

    }
4

4 に答える 4

3

これを試して...

int main()
{
    std::vector<int> v{1,2,3,4,5,6,7,8,9,10};
    std::vector<int> v2;

    std::vector<int>::const_iterator
        it = std::remove_copy_if(v.begin(), v.end(),
                                 std::back_inserter(v2),
                                 [](int const& i){return i <= 5;});
    v.erase(it, v.end);

    return 0;

}

remove_copy_ifcppreference.comで詳細を読むことができます。述語が true を返さない限り、入力範囲から要素を削除し、それらを出力にコピーします

これは STL のremoveであるため、後で erase を呼び出して入力を縮小する必要があることに注意してください。このソリューションのセマンティクスは、投稿したコードとは少し異なりますが、必要なものの説明に似ています。

于 2013-03-11T08:46:43.160 に答える
2

これをチェックしてください、私はあなたのコードにいくつかの変更を加えました:

template <typename iterator, typename Container, typename T>
void move_if(iterator a, iterator b, Container &o, T pred)
{
    for (auto i = a; i != b; i++)
    {
        if (pred(*i))
            o.insert(o.begin(), *i);
    }
}

int main()
{
    vector<int>v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    vector<int>v2;

    move_if(v.begin(), v.end(), v2, [](int i) { return !(i > 5); });
}

注: コメントのように、機能が上記のコードの場合は、名前move_ifをに変更することをお勧めします。それ以外の場合は、実際に項目を移動する必要があります。copy_if

于 2013-03-11T08:47:29.717 に答える
1

2番目の引数として述語をとるstd::vector :: insertのオーバーロードはないので、この行は間違っています:

o.insert(o.begin(),pred);

さらに、述語は引数を使用して呼び出す必要があります。

pred(someArg);

あなたの場合はstd::vector<int>::iterator。また、save_ifと同じではありませんmove_if。しかし、もっと重要なことは、あなたが何を達成しようとしているのかがまったく明確ではないということです。

于 2013-03-11T08:42:18.983 に答える
1

[](){return true}C++11 では、何もキャプチャしないようなステートレス ラムダは、暗黙的に関数ポインターに変換できます。if(pred)そうするとき、ステートレスラムダを関数ポインターに変換し、そのポインターが非nullであるかどうかを確認します(非nullです) 。これはあなたがしたいことではありません。

moveこれは、間bにあるものを移動する必要があると言うe実装です。pred(x)

template <typename iterator, typename Container, typename T>
void move_if(iterator b, iterator e, Container o, T pred)
{
  for( auto i = b; i != e;++i) {
    if(pred) {
      o.insert(o.end(),std::move(*i));
    }
  }
}

o.end()に挿入したことに注意してContainerください。必要なのはおそらくであり、 of にvector挿入する方がはるかに高速だからです。end()vector

std::back_inserter実際には、おそらく出力イテレータを取得し (デフォルトではfrom aを使用)、それにデータを出力したいと思うでしょうContainer。同様に、要素を-の範囲でremove_move_ifシャッフルし、 .beiterator

最後に、範囲ベースのアルゴリズムは書く価値があります。begin/end イテレータのペアを取得する代わりに、begin/endを返すようにオーバーライドされbegin(c)た1 つのオブジェクトを取得します。end(c)サブ範囲で作業している場合は、structbegin/end を適切にオーバーライドして、反復子の begin/end 範囲を渡すことができます。

于 2013-03-11T14:35:58.133 に答える