La variable membre non statique peut-elle être modifiée dans le constructeur constexpr (C ++ 14)?

struct A { int a = 0; constexpr A() { a = 1; } }; constexpr bool f() { constexpr A a; static_assert(aa == 1, ""); // L1: OK return aa == 1; } static_assert(f(), ""); // L2: Error, can not modify A::a in constexpr 
  • URL du compilateur en ligne: http://goo.gl/jni6Em
  • Compilateur: Clang 3.4 (avec -std = c ++ 1y)
  • Système: Linux 3.2

Si je supprime L2, ce code est compilé. Si j’ajoute L2, le compilateur se plaint “la modification d’object de type qualifié de const ‘const int’ n’est pas autorisée dans une expression constante”. Je ne suis pas un juriste linguistique, donc je ne suis pas sûr que cela soit vrai. Cependant, si c’est le cas, pourquoi le compilateur ne s’est-il pas plaint de L1, puisqu’il a également appelé A () en tant que constexpr? Est-ce un bug de clang? Ou ai-je manqué quelque chose?

Référence: http://fr.cppreference.com/w/cpp/language/constexpr

BTW, si je change “constexpr A a;” à “A a;” (supprimer le mot clé constexpr), L1 n’a pas pu comstackr ce qui est attendu. Cependant, le compilateur ne se plaint plus de L2.

URL du compilateur en ligne à ce sujet: http://goo.gl/AoTzYx

Je pense qu’il s’agit simplement de compilateurs qui n’ont pas rattrapé les modifications proposées pour C ++ 14. Votre constructeur constexpr remplit toutes les conditions énumérées au § 7.1.5 / 4 de N3936 . Gcc et clang ne parviennent pas à comstackr votre code, mais pour des raisons différentes.

Clang se plaint:

Remarque: la modification d’object de type qualifié const ‘const int’ n’est pas autorisée dans une expression constante.

ce qui n’a pas beaucoup de sens, mais me rappelle la ressortingction C ++ 11 que les fonctions membres de constexpr sont implicitement const (ceci est un constructeur, et cela ne s’applique pas, mais le message d’erreur le rappelle). Cette ressortingction a également été levée pour C ++ 14.

Le message d’erreur de gcc est:

erreur: le constructeur constexpr n’a pas de corps vide

Il semble assez clair que gcc implémente toujours les règles C ++ 11 pour les constructeurs constexpr .

De plus, N3597 énumère cet exemple:

 struct override_raii { constexpr override_raii(int &a, int v) : a(a), old(a) { a = v; } constexpr ~override_raii() { a = old; } int &a, old; }; 

N3597 a été remplacé par N3652 , qui contient le libellé trouvé dans le projet actuel. Malheureusement, l’exemple précédent disparaît mais, encore une fois, rien dans la formulation actuelle n’indique que vous ne pouvez pas affecter de valeurs aux membres de données dans le corps d’un constructeur constexpr .

Mise à jour (2017-10-03)

clang a corrigé cela, mais il n’y a pas encore de nouvelle version: https://bugs.llvm.org/show_bug.cgi?id=19741 ( explorateur du compilateur )