Actualización: como lo prometió el presidente de Core en la cita inferior, el código ahora está mal formado :
Si un identificador en una sencilla captura aparece como el declarador-id de un parámetro de la lambda-declarador 's declaración-parámetro-cláusula , está mal formado el programa.
Hubo algunos problemas relacionados con la búsqueda de nombres en lambdas hace un tiempo. Fueron resueltos por N2927 :
La nueva redacción ya no se basa en la búsqueda para reasignar los usos de las entidades capturadas. Niega más claramente las interpretaciones de que la declaración compuesta de una lambda se procesa en dos pasadas o que cualquier nombre en esa declaración compuesta podría resolver a un miembro del tipo de cierre.
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 :
La lambda-expresión 's compuesto declaración produce el cuerpo de la función ([dcl.fct.def]) del operador llamada a la función, pero para fines de búsqueda de nombre, [...], el compuesto declaración se considera en el contexto de La expresión lambda . [ Ejemplo :
struct S1 {
int x, y;
int operator()(int);
void f() {
[=]()->int {
return operator()(this->x+y); // equivalent to: S1::operator()(this->x+(*this).y)
// and this has type S1*
};
}
};
- ejemplo final ]
(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ámetro foo
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 de foo
, 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ó
Este es el número 2211 (en breve aparecerá una nueva lista de problemas en el sitio open-std.org, desafortunadamente con solo marcadores de posición para varios problemas, de los cuales este es uno; estoy trabajando duro para llenar esos vacíos antes de Kona reunión a fin de mes). CWG discutió esto durante nuestra teleconferencia de enero, y la dirección es hacer que el programa esté mal formado si un nombre de captura también es un nombre de parámetro.