Capture lambda d’un object constexpr

GCC 4.7.2 comstack ceci:

constexpr int i = 5; []{ std::integral_constant(); }; // nonstandard: i not captured 

mais pas ceci:

 constexpr int i = 5; [&i]{ std::integral_constant(); }; // GCC says i not constexpr 

Ce dernier exemple me semble correct, selon C ++ 11 §5.1.2 / 15:

Une entité est capturée par référence si elle est capturée implicitement ou explicitement mais non par copie. Il n’est pas précisé si des membres de données non nommés non statiques supplémentaires sont déclarés dans le type de fermeture pour les entités capturées par référence.

Il semble que l’object capturé à l’intérieur du lambda se réfère à la variable de la scope englobante, qui est constexpr , pas simplement une référence const .

La norme indique explicitement que l’utilisation d’une capture par valeur est transformée en une utilisation du membre correspondant de l’object lambda. Et je pense que 5.1.2 laisse entendre que mon interprétation est correcte.

Y a-t-il quelque chose qui indique explicitement que si une capture par référence fait référence à l’object dans la scope englobante ou à une référence?

Le deuxième modèle-argument de std::integral_constant< int, i > est destiné à un modèle-paramètre de type non-type , en particulier de type intégral ou enumeration (14.3.2p1 bullet 1) et doit donc être une expression constante convertie de type int .

Dans une expression lambda , la capture implicite se produit lorsqu’une entité est odr-utilisée dans l’instruction composée (5.1.2p11); L’utilisation d’une expression constante convertie dans une instanciation de modèle explicite n’est pas odr-use (3.2p3). Le premier exemple est donc valide.

Dans le deuxième exemple, je pense que gcc n’est pas correct de le rejeter; 5.1.2p17 dit dans une note que:

Une expression id qui n’est pas une odr-utilisation fait référence à l’entité d’origine, jamais à un membre du type de fermeture.

Bien que le paragraphe dans son ensemble traite de la capture par copie, il n’y a aucune raison de ne pas appliquer cette règle à la capture par référence également. Il n’est pas surprenant que la norme ne soit pas claire à ce sujet. il n’y a vraiment aucune raison de capturer une entité qui peut être utilisée dans une expression constante convertie par référence.

Premièrement, je peux confirmer votre observation avec gcc 4.6.3 et clang 3.0 sur Ubuntu 12.04.

Je n’ai pas le standard C ++ 11 (uniquement le brouillon), donc je ne peux pas en parler. Mais regardez les, de ma compréhension, les déclarations équivalentes

 constexpr int i = 5; const int &j = i; std::integral_constant(); 

Ni gcc, ni clang ne comstacknt cela, car j n’est pas une “constante intégrale”.