2011-07-10 10 views
3

だから私はでおよそC++ 0xのFAQSページでBjarneにより、簡単な例をもとに、それが使用されるスコープのローカル変数にアクセスするラムダをテストしようとしていた:私はこれをしようとすると http://www2.research.att.com/~bs/C++0xFAQ.html#lambdastd :: fill()にC++ 0x lambdasローカル変数を使用するには?

簡単なテストコード:

#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 ::埋める()署名がconst型&を必要と示し新しい値要素の割り当てに使用します。

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

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

+5

残りのエラーメッセージはどこにありますか? –

+0

Eww。 update post :) –

+0

ここでの正確な機能は、新しいC++ 0xアルゴリズム( 'std :: iota')によって実装されていることに注意してください。 – ildjarn

答えて

15

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

あなたが探している機能はstd::generateです。

+2

正解、私は例を見て少し混乱しました。 – Xeo

+0

ありがとうNicol!あなたのアドバイスは完璧に機能し、 –

1

はこれを試してみてください:

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

it

は現在、ベクターの内容を反復され、基準を経由して来ています。

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; 
    } 
} 

おかげで、私はこれをはるかに簡単なアプローチを見つけます。関数オブジェクトを取るアルゴリズムのために今からlambdaを使用している可能性が非常に高いです!



アップデート2:

上記の元記事へのildjarnさんのコメントに基づいて: 「ここに正確な機能は、新しいC++ 0xのアルゴリズムによって実装されていることに注意してください - のstd ::イオタ "

テストの後、私はに適切なコードを変更した:

... 
#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); 
} 
... 

、それが正常に動作しています。 (「Iota」、N3242のs26.7.6)。

シンプルでクリーンな(少しはっきりしていませんが)、読みやすく、さらに重要なのはメンテナンスです。

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

関連する問題