Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 78 di 93
  • livello avanzato
Indice lezioni

Espressioni lambda generiche

In C++, la programmazione generica è estesa anche alle espressioni lambda, apponendo lo specificatore auto davanti ad uno o più argomenti dell'espressione.
In C++, la programmazione generica è estesa anche alle espressioni lambda, apponendo lo specificatore auto davanti ad uno o più argomenti dell'espressione.
Link copiato negli appunti

L'introduzione dallo standard C++14 ha consentito di estendere il paradigma della programmazione generica anche alle espressioni lambda.

A differenza di altre entità invocabili, come classi e funzioni, per le espressioni lambda ciò avviene apponendo lo specificatore auto davanti uno o più argomenti dell'espressione.

Come esempio si consideri il listato seguente in cui si mostra l'uso di una espressione lambda generica che stampa a schermo il valore del suo argomento:

#include <iostream>
 
int main()
{
    auto lambda1 = [](auto x) { std::cout << x << '\n'; };
    lambda1("hello world");
    lambda1(2);
    lambda1(2.5);
     
    return 0;
}

Grazie al meccanismo di inferenza dei tipi, per l'oggetto lambda1 viene di volta in volta istanziato un sovraccarico dell'operatore di chiamata a funzione operator() idoneo per il tipo della variabile passata come argomento.

Il compilatore non solleva eccezioni fin tanto che il tipo dell'argomento è provvisto di un sovraccarico dell'operatore di inserimento operator<< per la classe std::cout, come nel caso di questo listato.

Come accennato in precedenza, si osservi che nello standard C++14, per le espressioni lambda non si ricorre in maniera esplicita all'uso del costrutto template, come invece avviene per la definizione di classi e funzioni generiche.

Esso è ovviamente alla base dell'implementazione di questo costrutto, ma è mascherato dall'effetto che lo specificatore auto ha sulla trasformazione della espressione lambda in una entità invocabile da parte del compilatore.

Per il listato precedente, ad esempio, la definizione dell'espressione lambda generica di cui sopra potrebbe tradursi nella definizione di una classe anonima dotata del sovraccarico template del metodo operator(), come mostrato nel frammento seguente:

class {
public:
    template<typename T>
    void operator()(T x) const
    {
        std::cout << x << '\n';
    }
};

L'uso dello specificatore auto come alternativa al costrutto template per la definizione di funzioni generiche non è limitata al caso delle espressioni lambda.

Anche le funzioni libere o i metodi di classe possono beneficiare del medesimo meccanismo di istanziazione, che rende implicito l'uso del costrutto template.

Tuttavia, è bene ricordare che pur essendo due modalità di definizione di funzioni generiche equivalenti in termini funzionali, sussistono comunque delle differenze a livello di capacità espressiva.

Nello specifico, l'uso dello specificatore auto non consente di catturare propriamente argomenti il cui tipo è a sua volta un tipo generico, ad esempio le classi contenitore.

Per questa ragione, la sintassi per la definizione di espressioni lambda generiche è stata rivista nello standard C++20, per consentire una migliore integrazione del costrutto template.

Secondo l'ultima revisione dello standard è infatti possibile definire espressioni lambda generiche usando una sintassi più omogenea ed al contempo espressiva, rispetto quella basata sullo specificatore auto, come mostrato nel frammento seguente:

// espressione generica C++14
auto lambda14 = [] (const auto& list) {
    std::cout << list.size() << '\n';
};
 
// espressione generica C++20
auto lambda20 = [] <typename T> (const std::list<T>& list) {
    std::cout << list.size() << '\n';
};

Lo standard C++20 consente infatti di apporre una clausola per la definizione dei tipi generici tra la clausola di cattura e la lista di argomenti dell'espressione lambda.

La possibilità di definire espressioni lambda generiche secondo la sintassi definita nello standard C++20 comporta notevoli vantaggi soprattutto per quanto riguarda la capacità diagnostica del compilatore, che in caso di errori relativi al controllo dei tipi emette messaggi di errore più comprensibili e mirati.


Ti consigliamo anche