Mise à jour: comme promis par le président Core dans la citation du bas, le code est maintenant mal formé :
Si un identifiant dans une simple capture apparaît comme le déclarateur-id d'un paramètre du lambda-declarator du paramètre-déclaration article , le programme est mal formé.
Il y a quelques temps, il y a eu quelques problèmes concernant la recherche de nom dans lambdas. Ils ont été résolus par N2927 :
Le nouveau libellé ne repose plus sur la recherche pour remapper les utilisations des entités capturées. Il nie plus clairement les interprétations selon lesquelles une instruction composée de lambda est traitée en deux passes ou que tous les noms de cette instruction composée pourraient être résolus en un membre du type de fermeture.
La recherche est toujours effectuée dans le contexte de l' expression lambda , jamais «après» la transformation en corps de fonction membre d'un type de fermeture. Voir [expr.prim.lambda] / 8 :
Le lambda-expression « de instruction_compound donne la fonction du corps ([dcl.fct.def]) de l'opérateur d'appel de fonction, mais à des fins de recherche par nom, [...], le instruction_compound est considéré dans le contexte de l' expression lambda . [ Exemple :
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*
};
}
};
- fin d'exemple ]
(L'exemple montre également clairement que la recherche ne considère pas en quelque sorte le membre de capture généré du type de fermeture.)
Le nom foo
n'est pas (re) déclaré dans la capture; il est déclaré dans le bloc contenant l'expression lambda. Le paramètre foo
est déclaré dans un bloc imbriqué dans ce bloc externe (voir [basic.scope.block] / 2 , qui mentionne également explicitement les paramètres lambda). L'ordre de recherche va clairement des blocs internes aux blocs externes . Par conséquent, le paramètre doit être sélectionné, c'est-à-dire que Clang a raison.
Si vous deviez faire de la capture un init-capture, c'est-à-dire foo = ""
au lieu de foo
, la réponse ne serait pas claire. En effet, la capture induit désormais une déclaration dont le "bloc" n'est pas donné. J'ai envoyé un message à la chaise principale à ce sujet, qui a répondu
Il s'agit du numéro 2211 (une nouvelle liste de problèmes apparaîtra sous peu sur le site open-std.org, malheureusement avec juste des espaces réservés pour un certain nombre de problèmes, dont celui-ci; je travaille dur pour combler ces lacunes avant le Kona réunion à la fin du mois). Le CWG en a discuté lors de notre téléconférence de janvier, et la direction est de rendre le programme mal formé si un nom de capture est également un nom de paramètre.