web-dev-qa-db-ja.com

C ++ 11で(同じ型の)ラムダのベクトルを作成できないのはなぜですか?

私はラムダのベクトルを作成しようとしましたが、失敗しました:

auto ignore = [&]() { return 10; };  //1
std::vector<decltype(ignore)> v;     //2
v.Push_back([&]() { return 100; });  //3

2行目まで、それは コンパイル可能 です。しかし、3行目では コンパイルエラー

エラー:「std :: vector <main():: <lambda()>> :: Push_back(main():: <lambda()>)」の呼び出しに一致する関数がありません

関数ポインターのベクトルまたは関数オブジェクトのベクトルは必要ありません。ただし、realラムダ式をカプセル化する関数オブジェクトのベクトルは、私にとってはうまくいくでしょう。これは可能ですか?

83
Nawaz

すべてのラムダには、同じシグネチャがある場合でも、異なるタイプがあります。そのようなことをしたい場合は、std::functionなどのランタイムカプセル化コンテナを使用する必要があります。

例えば。:

std::vector<std::function<int()>> functors;
functors.Push_back([&] { return 100; });
functors.Push_back([&] { return  10; });
128
Puppy

すべてのラムダ式は、タイプが異なります文字ごとに同じ場合でも。異なる型のラムダを(別の式であるため)ベクトルにプッシュしており、明らかに動作しません。

1つの解決策 は、代わりにstd::function<int()>のベクトルを作成することです。

auto ignore = [&]() { return 10; };
std::vector<std::function<int()>> v;
v.Push_back(ignore);
v.Push_back([&]() { return 100; });

別の注意として、何もキャプチャしていないときに[&]を使用するのは得策ではありません。

39

他の人が言ったことは関連していますが、ラムダのベクトルを宣言して使用することはまだ可能ですが、あまり有用ではありません:

auto lambda = [] { return 10; };
std::vector<decltype(lambda)> vector;
vector.Push_back(lambda);

したがって、lambdaのコピー/移動である限り、そこに任意の数のラムダを格納できます。

17
Luc Danton

ラムダがステートレス、つまり[](...){...}の場合、C++ 11ではラムダを関数ポインターに分解できます。理論的には、C++ 11準拠のコンパイラはこれをコンパイルできます。

auto ignore = []() { return 10; };  //1 note misssing & in []!
std::vector<int (*)()> v;     //2
v.Push_back([]() { return 100; });  //3
15
MSN

ラムダ生成関数を使用できます(Nawazによって提案された修正で更新されます):

#include <vector>
#include <iostream>

int main() {
    auto lambda_gen = [] (int i) {return [i](int x){ return i*x;};} ;

    using my_lambda = decltype(lambda_gen(1));

    std::vector<my_lambda> vec;

    for(int i = 0; i < 10; i++) vec.Push_back(lambda_gen(i));

    int i = 0;

    for (auto& lambda : vec){
        std::cout << lambda(i) << std::endl;
        i++;
    }
}

しかし、この時点で基本的に独自のクラスを作成したと思います。そうでない場合、ラムダのcaputres/argsなどが完全に異なる場合は、おそらくタプルを使用する必要があります。

4
antediluvian

各ラムダは異なるタイプです。 std::Tupleの代わりにstd::vectorを使用する必要があります。

3
Paul Fultz II