Espressioni Lambda
Nella lezione precedente abbiamo faticato costruendo intere e verbose struct unicamente per sovraccaricare un operator(). Se devo passare un oggettino volante a std::sort solo una volta per ordinare degli elementi, non voglio inquinare il file scrivendo classi e costruttori!
Il C++ ha introdotto le Lambda Expressions (Funzioni Anonime). Le Lambda sono in assoluto la sintassi più rapida e meravigliosa per generare Funtori (Function Objects) “usa-e-getta” al volo.
Struttura di una Lambda
Section titled “Struttura di una Lambda”Una lambda consta in 5 sezioni (molte delle quali opzionali):
[Catture] (Parametri) Modificatori -> TipoRitorno { Corpo }
Il tipo di ritorno è quasi sempre dedotto in automatico (auto), e spesso anche i Modificatori sono evitati. Rimane il nòcciolo vitale:
[Catture](Parametri){ Corpo };
Le Catture (Capture List)
Section titled “Le Catture (Capture List)”Il blocco parentesi quadre [] all’inizio si chiama Capture List. È ciò che permette alla tua funziona volante di “Catturare” (ingerire) le variabili locali del blocco in cui viene definita. È l’equivalente sintattico di passare parametri al costruttore del tuo Functor e salvarli in variabili di stato interne!
Se sei davvero pigro, puoi usare le Catture di Default:
[=]Cattura in automatico qualsiasi cosa scrivi nel corpo passandotelo per COPIA.[&]Cattura in automatico qualsiasi variabile che tu scriva, per REFERENZA.
Avvertenza di sicurezza: Sebbene seducente, usare
[&]è pericoloso se passi questa Lambda in giro (magari ad altri thread). Il bloccomainpotrebbe spegnersi, la variabile morirebbe e la Lambda punterebbe al vuoto causando Segmentation Fault. È preferibile scrivere in modo esplicito (Named Capture)[&mio_valore]per capire subito chi ha i permessi di lettura/scrittura.
Mutable Lambdas
Section titled “Mutable Lambdas”Normalmente le variabili catturate per valore (Copia) divengono const internamente e non puoi modificarle per fare calcoli (sono in Read-Only all’interno del corpo { }).
Per renderle alterabili (senza però riflettere le modifiche fuori all’esterno) basta usare il modificatore mutable:
[copia_tally]() mutable { copia_tally++; };
Generic Lambdas (Lambda con Auto)
Section titled “Generic Lambdas (Lambda con Auto)”Con le Generic Lambdas puoi mescolare la magia dei Template con le funzioni anonime in una formula spettacolare.
Basta rimpiazzare i tipi dei parametri con la parola auto.
// Il compilatore estrae un template su due piedi!auto translate = [](auto x) { return 10 * x + 5; };
// Potro' passargli INT (chiamera' l'instanziazione int)int a = translate(10);// O double (chiamera' l'instanziazione double)double b = translate(5.5);Tutte le Lambda create possono essere valutate in un regime constexpr in C++17 se rispettano i vincoli. Scrivere algoritmi pesanti che si autocalcolano nel silicio durante la compilazione non è mai stato così snello ed elegante.