4

そこで、C++0x FAQS ページ ( http://www2.research.att.com/ ) の Bjarne による簡単な例に基づいて、ラムダが使用されているスコープ内のローカル変数にアクセスするラムダをテストしようとしました。 ~bs/C++0xFAQ.html#ラムダ

この簡単なテスト コードを試すと、次のようになります。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

//Test std::fill() with C++0x lambda and local var
void f (int v) { 
    vector<int> indices(v);
    int count = 0;
    fill(indices.begin(), indices.end(), [&count]() {
        return ++count;
    });

    //output test indices
    for (auto x : indices) {
        cout << x << endl;
    }
}

int main() {
    f(50);
}

エラーが発生します:

required from 'void std::fill(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >, _Tp = f(int)::<lambda()>]'

この errmsg は、 std::fill() 署名が新しい値要素の割り当てに使用するために const Type& を必要とすることを示していると思います。

しかし、Bjarne の例で示されているように、この目的で fill() を使用できるようにするには、ラムダ キャプチャ句内で参照 '[&count]' を使用して元の値を再割り当てできるようにする必要があるのではないでしょうか。 'return ++count;' を介してインクリメントするカウント var で要素値をインデックス付けします。ラムダステートメントブロック?

私はまだこれらのラムダについて完全に理解していないことを認めます! :)

4

3 に答える 3

16

Bjarne の例はコンパイルされません。std::fillC++0x で別様に定義されていない限り、コンパイルできません。関数を取ることができる概念化されたバージョンからのものだったのかもしれませんstd::fillが、実際のバージョン (N3242 のセクション 25.1 によると) は関数ではなくobjectを取ります。そのオブジェクトをリストのすべての要素にコピーします。その人がやろうとしていることです。

お探しの機能はstd::generate.

于 2011-07-10T07:11:56.913 に答える
1

これを試して:

for_each(indices.begin(), indices.end(), [&count](int& it) 
{        
    it = ++count;    
});

it現在、ベクターのコンテンツが繰り返されており、参照経由で提供されます。

于 2011-07-10T13:09:22.247 に答える
1

これと同じ質問をする可能性のある将来の読者のために、「更新」スタイルの回答を追加しても問題ないことを願っています。私はここに新しいので教えてください。

だから、これが私が望んでいることをするコードの最終的な作り直された形式です:

#include <iostream>
#include <vector>
#include <algorithm>

//Overwrite a vector<int> with incrementing values, base-n.
void init_integers(std::vector<int>& ints, int base) {
    int index{ base };
    std::generate(ints.begin(), ints.end(), [&index]() {
        return index++;  //post-incr.
    });
}

//Default wrapper to overwrite a vector<int> 
// with incrementing values, base-0.
void init_integers(std::vector<int>& ints) {
    init_integers(ints, 0);
}

//Test lambda-based vector<int> initialization.
int main() {
    std::vector<int> indices( 50 );
    init_integers(indices);

    //test output loaded indices.
    for (auto x : indices) {
        std::cout << x << std::endl;
    }
}

役立つ回答をありがとう、これははるかに簡単なアプローチだと思います。関数オブジェクトを受け取るアルゴリズムには、これからラムダを使用する可能性が非常に高くなります!



更新 2:

上記の元の投稿に対するildjarnのコメントに基づいています:

テスト後、適切なコードを次のように変更しました。

...
#include <numeric>

//Overwrite a vector<int> with incrementing values, base-n.
void init_integers(std::vector<int>& ints, int base) {
    std::iota(ints.begin(), ints.end(), base);
}
...

そしてそれはうまくいっています。(N3242の「イオタ」、s26.7.6)。

シンプルでクリーンなほど (少しあいまいですが)、読みやすく、さらに重要なことに、保守が容易になります。

ありがとうございます!(個人的には、C++0x ラムダについてさらに洞察を得るためにこのプロセスを実行するのは良い練習になりました!) :) -Bud Alverson

于 2011-07-10T19:18:33.670 に答える