web-dev-qa-db-fra.com

Utiliser auto dans une fonction lambda

#include <vector>
#include <algorithm>

void foo( int )
{
}

int main()
{
  std::vector< int > v( { 1,2,3 } );

  std::for_each( v.begin(), v.end(), []( auto it ) { foo( it+5 ); } );
}

Une fois compilé, l'exemple ci-dessus démarre la sortie d'erreur comme ceci:

h4.cpp: In function 'int main()':
h4.cpp:13:47: error: parameter declared 'auto'
h4.cpp: In lambda function:
h4.cpp:13:59: error: 'it' was not declared in this scope

Cela signifie-t-il que le mot clé auto ne doit pas être utilisé dans les expressions lambda?

Cela marche :

std::for_each( v.begin(), v.end(), []( int it ) { foo( it+5 ); } );

Pourquoi la version avec le mot-clé auto ne fonctionne pas?

39
BЈовић

le mot clé auto ne fonctionne pas comme type pour les arguments de fonction, en C++ 11. Si vous ne souhaitez pas utiliser le type réel dans les fonctions lambda, vous pouvez utiliser le code ci-dessous.

 for_each(begin(v), end(v), [](decltype(*begin(v)) it ){
       foo( it + 5);         
 });

Le code de la question fonctionne très bien en C++ 14.

67
Jagannath

C++ 14 permet aux paramètres de la fonction lambda (fonction lambda générique) d'être déclarés avec l'auto.

auto multiply = [](auto a, auto b) {return a*b;};

Pour plus de détails: http://en.cppreference.com/w/cpp/language/lambda

22
Razan Paul

Herb Sutter en a discuté brièvement lors d'une entrevue. Votre demande d'arguments auto n'est en fait pas différente de la demande que la fonction any soit déclarable avec auto, comme ceci:

auto add(auto a, auto b) -> decltype(a + b) { return a + b; }

Cependant, notez que ce n'est pas vraiment une fonction du tout, mais plutôt une fonction template, semblable à:

template <typename S, typename T>
auto add(S a, T b) -> decltype(a + b) { return a + b; }

Donc, vous demandez essentiellement une facilité pour transformer n'importe quelle fonction en modèle en changeant ses arguments. Étant donné que les modèles sont une sorte d'entité très différente dans le système de type de C++ (pensez à toutes les règles spéciales pour les modèles, comme la recherche et la déduction en deux phases), ce serait un changement de conception radical avec des ramifications imprévisibles, ce qui n'est certainement pas '' t va être dans la norme de sitôt.

20
Kerrek SB

Le type de lambda doit être connu avant que le compilateur puisse même instancier std::for_each. D'un autre côté, même si c'était théoriquement possible, que auto ne pouvait être déduit qu'après l'instanciation de for_each En voyant comment le foncteur était appelé.

Dans la mesure du possible, oubliez for_each, Et utilisez des boucles basées sur des plages qui sont beaucoup plus simples:

for (int it : v) { 
   foo(it + 5); 
}

Cela devrait également bien fonctionner avec auto (et auto& Et const auto&).

for (auto it : v) { 
   foo(it + 5); 
}
4
visitor