Qual è la necessità del modello lambda introdotto in C ++ 20 quando C ++ 14 ha già un lambda generico?


99

ha introdotto lambda generici che hanno permesso di scrivere quanto segue:

auto func = [](auto a, auto b){
    return a + b;
};
auto Foo = func(2, 5);
auto Bar = func("hello", "world");

È molto chiaro che questo lambda generico funcfunziona proprio come funzionerebbe una funzione basata su modelli func.

Perché il comitato C ++ ha deciso di aggiungere la sintassi del modello per lamda generico?


5
Cosa succede se è necessario utilizzare un tipo di modello diverso rispetto agli argomenti o al tipo restituito? E se fosse necessario all'interno del corpo?
Un tizio programmatore il

Mi è stato detto che questo era un caso d'uso interessante.
Max Langhof

Vedi questo per un confronto tra le diverse versioni lambda: modernescpp.com/index.php/more-powerful-lambdas-with-c-20
schoetbi

Risposte:


115

I lambda generici C ++ 14 sono un modo molto interessante per generare un funtore con un operator ()aspetto simile a questo:

template <class T, class U>
auto operator()(T t, U u) const;

Ma non così:

template <class T>
auto operator()(T t1, T t2) const; // Same type please

Né così:

template <class T, std::size_t N>
auto operator()(std::array<T, N> const &) const; // Only `std::array` please

Né in questo modo (anche se questo diventa un po 'complicato da usare effettivamente):

template <class T>
auto operator()() const; // No deduction

I lambda C ++ 14 vanno bene, ma C ++ 20 ci consente di implementare questi casi senza problemi.


2
Bello e conciso. Aggiungendo solo questo: il primo (stessi tipi) può essere risolto (auto a, decltype(a) b)in C ++ 14.
Sebastian Mach,

13
@SebastianMach quasi. Con quella soluzione bnon viene dedotto, e il suo argomento verrà convertito implicitamente nel tipo di ainvece.
Quentin,

32

Poiché è possibile utilizzare espressioni lambda basate su modelli in C ++ 20, è possibile limitare i tipi in un modo più semplice rispetto a un'espressione SFINAE:

auto lambda = []<typename T>(std::vector<T> t){};

Questo lambda funzionerà solo con i tipi di vettore.


8
Qual è la constevalrelazione con la nuova sintassi? È bello e tutto, ma non capisco la pertinenza.
StoryTeller - Unslander Monica

È più un'informazione su ciò che C ++ 20 aggiunge all'espressione lambda che una risposta alla domanda
Antoine Morrier

24

La proposta che è stata accettata in C ++ 20 ha una lunga sezione di motivazione, con esempi. La premessa è questa:

Ci sono alcuni motivi chiave per cui l'attuale sintassi per la definizione di espressioni lambda generiche è considerata insufficiente dall'autore. L'essenza è che alcune cose che possono essere fatte facilmente con i normali modelli di funzioni richiedono un salto di cerchio significativo da fare con lambda generici, o non possono essere fatte affatto. così come i normali modelli di funzioni.

Di seguito sono riportati alcuni esempi.


21

La nuova "sintassi familiare del modello" per le espressioni lambda introdotte in C ++ 20 rende i costrutti come  for_types e  for_range praticabili e molto più leggibili rispetto alle alternative C ++ 17.

(fonte: iterazione in fase di compilazione con C ++ 20 lambda )

Un'altra cosa interessante che può essere eseguita su lambda generici C ++ 14 e C ++ 17 è la chiamata diretta  operator() passando esplicitamente un parametro del modello:

C ++ 14:

   auto l = [](auto){ };
   l.template operator()<int>(0);

C ++ 20:

  auto l = []<typename T>(){ };
  l.template operator()<int>();

L'esempio C ++ 14 sopra è abbastanza inutile: non c'è modo di fare riferimento al tipo fornito  operator() nel corpo del lambda senza dare un nome all'argomento e usare  decltype. Inoltre, siamo costretti a passare un argomento anche se potremmo non averne bisogno.

L'esempio C ++ 20 mostra come T sia facilmente accessibile nel corpo del lambda e che un lambda nullo possa ora essere modellato arbitrariamente. Questo sarà molto utile per l'implementazione dei suddetti costrutti in fase di compilazione

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.