auto foo = "You're using g++!";
auto compiler_detector = [foo](auto foo) { std::puts(foo); };
compiler_detector("You're using clang++!");
clang ++ 3.6.0 y versiones posteriores imprimen "¡Estás usando clang ++!" y advertir sobre la captura
foo
no utilizada.g ++ 4.9.0 y versiones posteriores imprimen "¡Estás usando g ++!" y advertir sobre el parámetro
foo
no utilizado.
¿Qué compilador sigue con mayor precisión el estándar C ++ aquí?
struct Lambda { template<typename T> void operator()(T foo) const { /* ... */ } private: decltype(outer_foo) foo{outer_foo}; }
.Respuestas:
Actualización: como lo prometió el presidente de Core en la cita inferior, el código ahora está mal formado :
Hubo algunos problemas relacionados con la búsqueda de nombres en lambdas hace un tiempo. Fueron resueltos por N2927 :
La búsqueda siempre se realiza en el contexto de la expresión lambda , nunca "después" de la transformación al cuerpo de la función miembro de un tipo de cierre. Ver [expr.prim.lambda] / 8 :
(El ejemplo también deja en claro que la búsqueda de alguna manera no considera el miembro de captura generado del tipo de cierre).
El nombre
foo
no se (re) declara en la captura; se declara en el bloque que encierra la expresión lambda. El parámetrofoo
se declara en un bloque que está anidado en ese bloque externo (consulte [basic.scope.block] / 2 , que también menciona explícitamente los parámetros lambda). El orden de búsqueda es claramente de bloques internos a externos . Por lo tanto, se debe seleccionar el parámetro, es decir, Clang es correcto.Si hiciera la captura una captura inicial, es decir, en
foo = ""
lugar defoo
, la respuesta no sería clara. Esto se debe a que la captura ahora induce una declaración cuyo "bloque" no se da. Le envié un mensaje al presidente central sobre esto, quien respondiófuente
Estoy tratando de reunir algunos comentarios a la pregunta para darle una respuesta significativa.
En primer lugar, tenga en cuenta que:
foo
Por lo tanto, la lógica me haría decir a primera vista que el parámetro debería sombrear la variable capturada como si estuviera en:
De todos modos, @nm notó correctamente que los miembros de datos no estáticos declarados para variables capturadas con copia en realidad no tienen nombre. Dicho esto, todavía se accede al miembro de datos sin nombre mediante un identificador (es decir
foo
). Por lo tanto, el nombre del parámetro del operador de llamada de función aún debería (déjame decir) sombrear ese identificador .Como señaló correctamente @nm en los comentarios a la pregunta:
Por eso, diría que el sonido metálico es correcto.
fuente