Il existe une propriété très soignée d'expressions constantes en C++: leur évaluation ne peut pas avoir un comportement indéfini ( 7.7.4.7 ):
Une expression e est une expression constante de base à moins que l'évaluation de e, suivant les règles de la machine abstraite ([intro.execution]), n'évalue l'un des éléments suivants:
...
une opération qui aurait un comportement non défini comme spécifié dans [intro] à [cpp] de ce document [Remarque: y compris, par exemple, un débordement d'entier signé ([expr.prop]), une certaine arithmétique de pointeur ([expr.add]), division par zéro, ou certaines opérations de décalage - note de fin];
Essayer de stocker la valeur de 13!
dans un constexpr int
en effet donne une belle erreur de compilation :
constexpr int f(int n)
{
int r = n--;
for (; n > 1; --n) r *= n;
return r;
}
int main()
{
constexpr int x = f(13);
return x;
}
Production:
9:19: error: constexpr variable 'x' must be initialized by a constant expression
constexpr int x = f(13);
^ ~~~~~
4:26: note: value 3113510400 is outside the range of representable values of type 'int'
for (; n > 1; --n) r *= n;
^
9:23: note: in call to 'f(3)'
constexpr int x = f(13);
^
1 error generated.
(BTW pourquoi l'erreur dit "appel à 'f (3)'", alors qu'il s'agit d'un appel à f (13)? ..)
Ensuite, je supprime constexpr
de x
, mais je crée f
a consteval
. Selon les docs :
consteval - spécifie qu'une fonction est une fonction immédiate, c'est-à-dire que chaque appel à la fonction doit produire une constante au moment de la compilation
Je m'attends à ce qu'un tel programme provoque à nouveau une erreur de compilation. Mais à la place, le programme se compile et s'exécute avec UB .
Pourquoi donc?
UPD: Les commentateurs ont suggéré qu'il s'agissait d'un bogue du compilateur. Je l'ai signalé: https://bugs.llvm.org/show_bug.cgi?id=43714
Il s'agit d'un bogue du compilateur. Ou, pour être plus précis, il s'agit d'une fonctionnalité "sous-implémentée" (voir le commentaire dans bugzilla ):
Ouaip - semble consteval n'est pas encore implémenté, selon: https://clang.llvm.org/cxx_status.html
(le mot clé a probablement été ajouté mais pas le support d'implémentation réel)