Le code suivant est très bien:
constexpr double square_cstxpr(double x) { return x * x; }
int main() {
const int test = 5;
constexpr double result = square_cstxpr((double)test);
}
Cependant, si le type de test
est changé de const int
à const double
, g ++ donne l'erreur suivante: the value of 'test' is not usable in a constant expression
.
Voir le code et la sortie de g ++ ici: http://coliru.stacked-crooked.com/a/2fe9b176c2b23798
Quelqu'un pourrait-il expliquer ce comportement?
Les variables non -constexpr
mais const
doivent être de type entier ou énumération pour pouvoir être utilisées dans des expressions constantes. Voir [expr.const]/2 :
une conversion de lvalue en rvalue, sauf si elle est appliquée à
(2.7.1) une glvalue non volatile de type intégrale ou énumération qui fait référence à un objet const non volatile complet avec une initialisation précédente, initialisé avec une expression constante, ou [..]
Les raisons de cette limitation doivent être principalement historiques. Les virgules flottantes ont été traitées avec soin lorsqu'il s'agit d'expressions constantes; pensez aux paramètres de modèle non-type. Cela est dû à leur comportement fortement dépendant de la plate-forme qui rend les calculs de temps de compilation moins mathématiques qu'ils ne devraient l'être.
De expression constante (expressions constantes de base):
10) Toute autre conversion implicite lvalue-to-rvalue, à moins que lvalue ...
a) est de type intégral ou énumération et fait référence à un objet const non volatile complet, qui est initialisé avec une expression constante
Cela signifie qu'ici:
const int test1 = 5;
constexpr double result1 = square_cstxpr((double)test1);
test1
est une expression constante, square_cstxpr
peut être appelé avec test1
comme argument au moment de la compilation et son résultat peut être affecté à variable constexprresult
.
D'un autre côté, ici:
const double test2 = 5;
constexpr double result2 = square_cstxpr((double)test2);
test2
n'est pas une expression constante car elle n'est pas de type intégral ou énumération. Par conséquent, square_cstxpr
ne peut pas être appelé au moment de la compilation avec test2
comme argument.