c++ - type - std::function




Warum kann ich in C++ 11 keinen Vektor von Lambdas(des gleichen Typs) erstellen? (4)

Ich habe versucht, einen Vektor von Lambda zu erstellen, aber gescheitert:

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

Bis Zeile 2, es kompiliert gut . Aber die Zeile # 3 gibt einen Kompilierungsfehler :

error: keine passende Funktion für den Aufruf von 'std :: vector <main () :: <lambda () >> :: push_back (main () :: <lambda ()>)'

Ich möchte keinen Vektor von Funktionszeigern oder Vektoren von Funktionsobjekten. Allerdings würde der Vektor von Funktionsobjekten, die echte Lambda-Ausdrücke einkapseln, für mich funktionieren. Ist das möglich?


Alle Lambda-Ausdrücke haben einen anderen Typ, auch wenn sie Zeichen für Zeichen identisch sind . Sie drücken ein Lambda eines anderen Typs (weil es ein anderer Ausdruck ist) in den Vektor, und das wird offensichtlich nicht funktionieren.

Eine Lösung besteht darin, stattdessen einen Vektor von std::function<int()> erstellen.

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

In einem anderen Fall ist es keine gute Idee, [&] wenn Sie nichts aufnehmen.


Jedes Lambda hat einen anderen Typ - auch wenn sie die gleiche Signatur haben. Sie müssen einen Laufzeit-Encapsulating-Container wie beispielsweise std::function wenn Sie so etwas tun möchten.

z.B:

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

Sie könnten eine Lambda-Erzeugungsfunktion verwenden (aktualisiert mit dem von Nawaz vorgeschlagenen Fix):

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

Aber ich denke, du hast im Grunde genommen deine eigene Klasse gemacht. Ansonsten, wenn die Lambdas völlig unterschiedliche caputres / args etc. haben, müssen Sie wahrscheinlich ein Tupel verwenden.


Während das, was andere gesagt haben, relevant ist, ist es immer noch möglich, einen Vektor von Lambda zu deklarieren und zu verwenden, obwohl es nicht sehr nützlich ist:

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

Sie können also beliebig viele Lambdas darin speichern, solange es sich um eine Kopie / Verschiebung von lambda !





c++11