J'essayais de créer un vecteur de lambda, mais j'ai échoué:
auto ignore = [&]() { return 10; }; //1
std::vector<decltype(ignore)> v; //2
v.push_back([&]() { return 100; }); //3
Jusqu'à la ligne n ° 2, il compile bien . Mais la ligne n ° 3 donne une erreur de compilation :
erreur: pas de fonction correspondante pour l'appel à 'std :: vector <main () :: <lambda () >> :: push_back (main () :: <lambda ()>)'
Je ne veux pas de vecteur de pointeurs de fonction ou de vecteur d'objets de fonction. Cependant, un vecteur d'objets de fonction qui encapsulent des expressions lambda réelles fonctionnerait pour moi. Est-ce possible?
Réponses:
Chaque lambda a un type différent, même s'ils ont la même signature. Vous devez utiliser un conteneur d'encapsulation au moment de l'exécution, par exemple
std::function
si vous souhaitez faire quelque chose comme ça.par exemple:
std::vector<std::function<int()>> functors; functors.push_back([&] { return 100; }); functors.push_back([&] { return 10; });
la source
std::function<int()
, pourrais-je utiliser différents prototypes de fonctions?vector
stockage à la foisstd::function
etstd::string
?" Et la réponse est la même: non, car ce n'est pas l'usage prévu. Vous pouvez utiliser une classe de style `` variante '' pour effectuer suffisamment d'effacement de type pour mettre des éléments disparates dans un conteneur, tout en incluant une méthode permettant à un utilisateur de déterminer le type `` réel '' et donc de choisir quoi faire (par exemple, comment appeler) chaque élément ... mais encore une fois, pourquoi aller si loin? Y a-t-il une réelle justification?Toutes les expressions lambda ont un type différent, même si elles sont identiques caractère par caractère . Vous poussez un lambda d'un type différent (car c'est une autre expression) dans le vecteur, et cela ne fonctionnera évidemment pas.
Une solution consiste à créer un vecteur de
std::function<int()>
.auto ignore = [&]() { return 10; }; std::vector<std::function<int()>> v; v.push_back(ignore); v.push_back([&]() { return 100; });
Sur une autre note, ce n'est pas une bonne idée à utiliser
[&]
lorsque vous ne capturez rien.la source
()
de lambdas qui ne prennent aucun argument.Bien que ce que d'autres ont dit soit pertinent, il est toujours possible de déclarer et d'utiliser un vecteur de lambda, bien que ce ne soit pas très utile:
auto lambda = [] { return 10; }; std::vector<decltype(lambda)> vec; vec.push_back(lambda);
Ainsi, vous pouvez stocker n'importe quel nombre de lambdas là-dedans, à condition qu'il s'agisse d'une copie / déplacement de
lambda
!la source
Si votre lambda est sans état, c'est-à-dire,
[](...){...}
C ++ 11 lui permet de se dégrader en un pointeur de fonction. En théorie, un compilateur compatible C ++ 11 serait capable de compiler ceci:auto ignore = []() { return 10; }; //1 note misssing & in []! std::vector<int (*)()> v; //2 v.push_back([]() { return 100; }); //3
la source
auto ignore = *[] { return 10; };
, feraitignore
un fichierint(*)()
.explicit
, le déréférencement d'une expression lambda est valide et déréférence le pointeur résultant de la conversion. Puis en utilisant desauto
désintégrations de cette référence en un pointeur. (Utilisantauto&
ouauto&&
aurait gardé la référence.)()
intentionnelle ou accidentelle?Vous pouvez utiliser une fonction de génération lambda (mise à jour avec le correctif suggéré par 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++; } }
Mais je pense que vous avez essentiellement créé votre propre cours à ce stade. Sinon, si les lambdas ont des caputres / arguments complètement différents, etc., vous devrez probablement utiliser un tuple.
la source
lambda_gen
qui peut être à son tour un lambda en lui-même. Cependant,auto a = lambda_gen(1);
effectue un appel inutile, ce qui peut être évité si nous écrivons cecidecltype(lambda_gen(1))
.decltype
n'est pas évalué , donc l'appel n'est pas réellement effectué. C'est le même cas avecsizeof
. De plus, ce code ne fonctionnera pas en C ++ 11 même si vous ajoutez un type de retour de fin !!Chaque lambda est d'un type différent. Vous devez utiliser à la
std::tuple
place destd::vector
.la source