Qual é a necessidade do modelo lambda introduzido no C ++ 20 quando o C ++ 14 já tem lambda genérico?

99

introduziu lambdas genéricos que tornaram possível escrever o seguinte:

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

É muito claro que este lambda genérico funcfunciona exatamente como uma função modelo funcionaria func.

Por que o comitê C ++ decidiu adicionar sintaxe de modelo para lamda genérico?

coder3101
fonte
5
E se você precisar usar um tipo de modelo diferente do que para os argumentos ou tipo de retorno? E se for necessário dentro do corpo?
Algum programador cara de
Disseram que este era um caso de uso interessante.
Max Langhof de

Respostas:

115

Lambdas genéricos do C ++ 14 são uma maneira muito legal de gerar um functor com um operator ()semelhante a este:

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

Mas não assim:

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

Nem assim:

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

Nem assim (embora seja um pouco complicado de usar):

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

Lambdas em C ++ 14 estão bem, mas C ++ 20 nos permite implementar esses casos sem complicações.

Quentin
fonte
2
Agradável e conciso. Apenas adicionando isto: O primeiro (mesmos tipos) pode ser resolvido (auto a, decltype(a) b)em C ++ 14.
Sebastian Mach
13
@SebastianMach quase. Com essa solução bnão é deduzida e seu argumento será convertido implicitamente para o tipo de a.
Quentin
32

Como você pode usar lambdas modelados em C ++ 20, pode restringir seus tipos de uma maneira mais fácil do que uma expressão SFINAE:

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

Este lambda funcionará apenas com tipos de vetor.

Antoine Morrier
fonte
8
Como está constevalrelacionado à nova sintaxe? É legal e tudo, mas não entendi a relevância.
StoryTeller - Unslander Monica
É mais uma informação sobre o que C ++ 20 adiciona à expressão lambda do que uma resposta à pergunta
Antoine Morrier
24

A proposta que foi aceita no C ++ 20 tem uma longa seção de motivação, com exemplos. A premissa é esta:

Existem algumas razões principais pelas quais a sintaxe atual para definir lambdas genéricas é considerada insuficiente pelo autor. A essência disso é que algumas coisas que podem ser feitas facilmente com os modelos de função normais requerem um salto significativo para ser feito com lambdas genéricos, ou não podem ser feitas de forma alguma. O autor pensa que lambdas são valiosos o suficiente para que C ++ deva suportá-los tão bem quanto modelos de funções normais.

A seguir estão alguns exemplos.

StoryTeller - Unslander Monica
fonte
21

A nova "sintaxe de modelo familiar" para lambdas introduzida no C ++ 20 torna as construções como  for_types e  for_range viáveis ​​e muito mais legíveis em comparação com as alternativas do C ++ 17.

(fonte: iteração em tempo de compilação com C ++ 20 lambdas )

Outra coisa interessante que pode ser feita em lambdas genéricos C ++ 14 e C ++ 17 é chamar diretamente  operator() , passando explicitamente um parâmetro de modelo:

C ++ 14:

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

C ++ 20:

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

O exemplo C ++ 14 acima é totalmente inútil: não há como se referir ao tipo fornecido  operator() no corpo do lambda sem dar um nome ao argumento e usar  decltype. Além disso, somos forçados a passar um argumento, embora possamos não precisar dele.

O exemplo C ++ 20 mostra como T é facilmente acessível no corpo do lambda e que um lambda nulo agora pode ser modelado arbitrariamente. Isso vai ser muito útil para a implementação das construções de tempo de compilação mencionadas

Hamza.S
fonte