c++ gcc lambda clang language-lawyer

c++ - ¿Es[]<typename>(){} una definición lambda válida?



gcc clang (2)

Estaba experimentando con lambdas y compiladores debido a otra pregunta aquí en SO.
Acabo de darme cuenta (y es perfectamente normal) que el siguiente código es válido:

int main() { auto l = [](){}; l.operator()(); }

En realidad, la norma dice que el tipo de cierre tiene un operador de llamada de función en línea pública, etc., por lo que tiene sentido poder invocarlo.

Lo que no puedo explicar al observar el estándar (bueno, el borrador de trabajo) es el hecho de que GCC (6.1) compila el siguiente fragmento de código (no clang 3.9):

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

No hay advertencias, no hay errores. ¿Es un código válido o debería ser rechazado por el compilador?


En N4140 5.1.2 [expr.prim.lambda], una expresión Lambda se define como

lambda-introducer lambda-declarator opt compuesto-enunciado

donde un "lambda-introducer" es el [] , adjuntando un opcional "lambda-capture" y "lambda-declarator opt " es lo que comienza con "(cláusula-declaración-parámetro)" .

[]<typename>(){}

no cumple con este requisito porque hay algo entre el introductor lambda y el declarador lambda, por lo que no es una expresión lambda válida.

Por lo tanto, su código de ejemplo no es válido en C ++ y debe ser rechazado por el compilador.

Como esto también está etiquetado como gcc , hice clic en la lista de extensiones GNU C ++ . No encontré ninguna extensión que hiciera que la sintaxis en cuestión fuera legal en GNU C ++.

Sin embargo, según la Sección 4 de P0428R0 (P0428R0), que propone agregar lambdas templadas a C ++, gcc obtuvo una implementación experimental del documento mencionado en 2009. Esto probablemente explica por qué gcc no se queja aquí.


Parece ser una extensión GCC (lambdas templadas).

#include <iostream> int main() { auto l = []<typename T>(T const& x){ std::cout << __PRETTY_FUNCTION__ << " " << x << std::endl;}; l(42); l("Hello world"); }

resultados en

main()::<lambda(const T&)> [with T = int] 42 main()::<lambda(const T&)> [with T = char [12]] Hello world