💡 Resumo:Lambdas do C++20 (parte 1): sintaxe de templates e restrições de tipos, e como o deducing this do C++23 torna lambdas recursivas numa linha sem std::function.
Última atualização:2026-10-31
Expressões Lambda no C++20 (parte 1)¶
Templates de lambda no C++20¶
O C++14 oferece suporte a expressões lambda genéricas, o que permite que uma lambda aceite parâmetros de qualquer tipo, por exemplo:
seria expandida para:
struct Func {
template <typename T1, typename T2>
auto operator()(T1 a, T2 b) const {
return a + b;
}
};
Porém, ela não consegue produzir as expansões abaixo:
Primeiro caso: mesmos tipos
Segundo caso: apenas std::array
Terceiro caso: sem dedução
As lambdas do C++14 são muito boas, mas o C++20 nos permite realizar esses casos com facilidade. O C++20 permite que expressões lambda usem parâmetros de tipo template em sua definição; a sintaxe básica é a seguinte:
A seguir, alguns exemplos ilustram seus benefícios.
1.Restrição de tipos¶
Em um exemplo como o abaixo, no C++14 podemos escrever o código a seguir; porém, ao usá-lo, o que é passado não é necessariamente um vector e, assim, o comportamento diverge do esperado, gerando erros.
A partir do C++20, podemos restringir o tipo:
Então surge a pergunta, uma questão de entrevista: você sabe como garantir segurança no C++14 para restringir a um vector?
2.Encaminhamento perfeito¶
No C++20, você pode usar o encaminhamento perfeito com muita facilidade; por exemplo:
Então surge a pergunta: em comparação com o C++14, qual é a vantagem? Ou seja, o que o C++14 precisaria para implementar o encaminhamento perfeito?
Fim desta seção
Lambdas recursivas com deducing this (C++23)¶
Uma lambda comum não consegue nomear a si mesma, então recursão significava guardar a lambda num std::function (alocação, indireção) ou envolvê-la num combinador-Y (engenhoso, ilegível). Os parâmetros de objeto explícitos do C++23 — o mesmo recurso deducing this — resolvem isso com elegância: a lambda recebe a si mesma como primeiro parâmetro:
// C++23 explicit object parameter: the lambda receives itself
auto factorial = [](this auto self, int n) -> long long {
return n <= 1 ? 1 : n * self(n - 1);
};
static_assert(factorial(10) == 3628800);
// before C++23 you needed std::function (heavy) or a Y-combinator (clever)
O parâmetro self é deduzido a cada chamada, então a recursão genérica também funciona: uma lambda pode recursar sobre qualquer tipo, e duas lambdas podem chamar uma à outra passando-se entre si. Como o compilador enxerga através de self, essas chamadas são inlinadas como se você tivesse escrito uma função nomeada.
Suporte: GCC 14+, Clang 18+, MSVC desde o VS 2022 17.2 — compile com -std=c++23.
Perguntas frequentes¶
Como escrevo uma lambda recursiva em C++?¶
Desde o C++23, dê à lambda um parâmetro de objeto explícito: [](this auto self, int n) { ... self(n-1) ... }. Antes disso: std::function, um combinador-Y, ou simplesmente uma função nomeada.
A lambda recursiva com deducing this é tão rápida quanto uma função normal?¶
Na prática, sim: o compilador especializa a chamada através de self e pode inliná-la, ao contrário da chamada indireta de std::function que a recursão pré-C++23 exigia.
Deducing this funciona com lambdas genéricas?¶
Sim. self é deduzido como auto&& a cada chamada, então a mesma lambda recursa sobre tipos diferentes, e duas lambdas podem até chamar uma à outra passando-se entre si.
Tópicos relacionados¶
- Introdução às corrotinas no C++20 | C++那些事
- Prática com channel no C++20 | C++那些事
- Concepts (conceitos) no C++20 | C++那些事
- constexpr e a expressão vírgula no C++20 | C++那些事
- Ordem de bytes (endian) no C++20 | C++那些事
- Módulos (Modules) no C++20 | C++那些事
- Biblioteca Ranges do C++20 | C++那些事
- Design e armadilhas do std::span no C++20 | C++那些事
- Guia dos novos recursos do C++20 | C++那些事
- [[likely]] e [[unlikely]] no C++20 | C++那些事