variable constexpr non capturée

Dec 10 2020

Le code suivant ne se compile pas en clang (il le fait dans GCC):

struct A{
    int a;
};

auto test(){
    constexpr A x{10};
    return []{
        return x; // <-- here x is A: clang doesn't compile
    }();
}

L'erreur de Clang est que la variable «x» ne peut pas être capturée implicitement dans un lambda sans spécification de capture par défaut , mais je pensais que les variables constexpr étaient toujours capturées.

Si x est un entier, le code se compile:

auto test(){
    constexpr int x{10};
    return []{
        return x; // <-- here x is int: clang is ok
    }();
}

Fait intéressant, le code suivant compile également:

auto test(){
    constexpr A x{10};
    return []{
        return x.a;
    }();
}

Est-ce que clang a raison? Si oui, quelle en est la justification? J'utilise -std = c ++ 17

--ÉDITER--

La question suivante: Puis-je utiliser une valeur constexpr dans un lambda sans la capturer? n'est pas lié à celui-ci, comme avec clang11 ce n'est plus un problème: en fait, comme indiqué ci-dessus, si x est un int, clang11 se compile.

Exemple de code également présent dans https://godbolt.org/z/rxcYjz

Réponses

2 DavisHerring Dec 25 2020 at 07:09

Lorsque vous return x;dans le premier exemple, vous devez invoquer Ale constructeur de copie de, ce qui implique de lier une référence à xet donc de l'utiliser. L'argument peut être fait qu'une copie triviale d'une valeur utilisable dans des expressions constantes ne devrait pas constituer une utilisation odr plus que return x.a;, mais il n'y a pas d'exception dans cette règle, donc Clang a raison de la rejeter.

En pratique, vous pouvez bien sûr faire n'importe quelle constexprvariable staticpour éviter tout besoin de la capturer.