2011-10-10 11 views
37
#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); }); 
} 

Quando compilato, l'esempio precedente avvia l'uscita errore come questo:Usando auto in una funzione lambda

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 

Vuol dire che la parola chiave auto non deve essere usato nelle espressioni lambda?

Questo funziona:

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

Perché la versione con la parola chiave auto non funziona?

+1

Penso che anche se è una lambda, esso continuerà a funzionare come una funzione, e deve avere una firma. Con l'auto lascia che il compilatore decida il tipo, quindi il tuo lambda non ha una vera firma fino al momento della compilazione. – Geoffroy

+3

Abbiamo davvero bisogno di lambda polimorfi (modelli impliciti AKA) nello standard successivo. Questa domanda è solo uno dei numerosi casi in cui le persone si limitano a pensare che "auto" funzioni in questo modo. Non vedo ragioni per cui non dovrebbe –

+0

deft_code, sono con te.È un caso logico di utilizzo per l'auto. – Robert

risposta

63

auto keyword non funziona come un tipo per argomenti di funzione. Se non si desidera utilizzare il tipo effettivo nelle funzioni lambda, è possibile utilizzare il codice riportato di seguito.

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

Avremo supporto 'auto' in lambdas in [C++ 14] (http://en.wikipedia.org/wiki/C%2B%2B14#Generic_lambdas). –

+0

Mente la stella prima di 'begin (v)' in 'decltype'. Si desidera che il tipo di valore non sia il tipo iteratore. (messaggi di errore quando fallisci sarà misterioso). –

4

Il tipo di lambda deve essere conosciuto prima il compilatore può anche istanziare std::for_each. D'altra parte, anche se fosse teoricamente possibile, che auto potesse essere dedotto solo dopo che for_each è stato istanziato osservando come viene richiamato il functor.

Se possibile, dimenticare for_each, e utilizzare gamma-based per i cicli che sono molto più semplice:

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

Questo dovrebbe anche far fronte bene con auto (e auto& e const auto&).

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

Sì, ma funziona solo con for_each e non con altri algoritmi. per esempio. vuoi ordinare su un lambda. – CashCow

20

Questo è stato discusso brevemente da Herb Sutter durante un'intervista. La vostra richiesta di auto argomenti è infatti non è diverso da chiedendo che qualsiasi funzione dovrebbe essere dichiarabile con auto, in questo modo:

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

Si noti tuttavia che questo non è davvero una funzione a tutti, ma piuttosto è un modello funzione di , simile a:

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

Così si chiedono in sostanza di un impianto per trasformare qualsiasi funzione in un modello, cambiando i suoi argomenti. Poiché i template sono un tipo di entità molto diverso nel sistema dei tipi di C++ (pensate a tutte le regole speciali per i template, come la ricerca e la deduzione in due fasi), questo sarebbe un radicale cambiamento di design con implicazioni imprevedibili, che certamente non è t sarà nello standard in qualunque momento presto.

+1

No, non chiedere o chiedere :) Mi chiedevo solo perché non funziona. –

+5

Bene, è essenzialmente la stessa ragione per "perché non sono tutti i modelli di funzioni" - semplicemente non si adatta al design del linguaggio. –

Problemi correlati