web-dev-qa-db-fra.com

La valeur d'une variable const est ou n'est pas utilisable dans une expression constante, selon le type de variable

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?

13
Georg

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.

6
Columbo

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.

7
Edgar Rokjān