Namespaces
Variants

Constant expressions

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Définit une expression qui peut être évaluée à la compilation.

De telles expressions peuvent être utilisées comme arguments de template constants, tailles de tableaux, et dans d'autres contextes nécessitant des expressions constantes, par exemple.

int n = 1;
std::array<int, n> a1;  // Erreur : « n » n'est pas une expression constante
const int cn = 2;
std::array<int, cn> a2; // OK : « cn » est une expression constante

Table des matières

Définition

Une expression qui appartient à l'une des catégories d'expressions constantes listées ci-dessous est une expression constante .

Catégories d'expressions constantes C++98

Expression constante intégrale (C++98)

Dans les contextes suivants, C++ requiert des expressions qui évaluent à une constante intégrale ou énumération :

Une expression satisfaisant toutes les conditions suivantes est une expression constante intégrale :

  • Elle n'implique que les entités suivantes :
  • littéraux de types arithmétiques
  • énumérateurs
  • variables ou membres de données statiques satisfaisant toutes les conditions suivantes :
  • Elles sont qualifiées const.
  • Elles ne sont pas qualifiées volatile.
  • Elles sont de types intégral ou énumération.
  • Elles sont initialisées avec des expressions constantes.
  • Elle n'utilise aucun littéral à virgule flottante, sauf s'ils sont explicitement convertis en types intégral ou énumération.
  • Elle n'applique aucune conversion vers des types non-intégraux et non-énumération.
  • Elle n'utilise aucune des entités suivantes sauf dans les opérandes de sizeof :
  • fonction
  • objet de classe
  • pointeur
  • référence
  • opérateur d'affectation
  • opérateur d'incrémentation
  • opérateur de décrémentation
  • opérateur d'appel de fonction
  • opérateur virgule

Autres catégories d'expressions constantes

D'autres expressions sont considérées comme des expressions constantes uniquement pour l' initialisation constante . Une telle expression constante doit être l'une des expressions suivantes :

  • une expression qui évalue à une valeur de pointeur nul
  • une expression qui évalue à une valeur de pointeur-vers-membre nul
  • une expression constante arithmétique
  • une expression constante d'adresse
  • une expression constante de référence
  • une expression constante d'adresse pour un type objet complet, plus ou moins une expression constante intégrale
  • une expression constante de pointeur-vers-membre

Une expression constante arithmétique est une expression satisfaisant les exigences pour une expression constante intégrale, avec les exceptions suivantes :

  • Les littéraux à virgule flottante peuvent être utilisés sans conversion explicite.
  • Les conversions vers des types à virgule flottante peuvent être appliquées.

Une expression constante d'adresse est une expression de type pointeur satisfaisant toutes les conditions suivantes :

  • utilisation explicite de l'opérateur adresse-de
  • utilisation implicite d'un paramètre de template constant de type pointeur
  • utilisation d'une expression de type tableau ou fonction
  • L'expression n'appelle aucune fonction.
  • L'expression utilise des conversions de pointeur explicites (sauf dynamic_cast ) et les opérateurs suivants sans accéder à l'objet résultat :
  • opérateur d'indice
  • opérateur d'indirection
  • opérateur adresse-de
  • opérateur d'accès membre
  • Si l'opérateur d'indice est utilisé, un de ses opérandes est une expression constante intégrale.

Une expression constante de référence est une expression de type référence satisfaisant toutes les conditions suivantes :

  • La référence désigne un objet de durée de stockage statique, un paramètre de template constant de type référence, ou une fonction. La référence ne désigne pas un membre ou classe de base de type classe non-POD.
  • L'expression n'appelle aucune fonction.
  • L'expression utilise des conversions de référence explicites (sauf dynamic_cast ) et les opérateurs suivants sans accéder à l'objet résultat :
  • opérateur d'indice
  • opérateur d'indirection
  • opérateur adresse-de
  • opérateur d'accès membre
  • Si l'opérateur d'indice est utilisé, un de ses opérandes est une expression constante intégrale.

Une expression constante de pointeur-vers-membre est une expression de type pointeur-vers-membre où le pointeur est créé en appliquant l'opérateur adresse-de à un identifiant qualifié, optionnellement précédé d'une conversion explicite de pointeur-vers-membre.

(jusqu'à C++11)

Les expressions suivantes sont collectivement appelées expressions constantes :

(depuis C++11)
(jusqu'à C++14)

Les entités suivantes sont des résultats autorisés d'une expression constante  :

  • les objets temporaires ayant une durée de stockage statique
  • les objets non temporaires avec durée de stockage statique dont les valeurs satisfont aux contraintes énumérées ci-dessous
  • les fonctions non immédiates (depuis C++20)

Une expression constante est soit une glvalue expression constante fondamentale qui se réfère à une entité qui est un résultat autorisé d'une expression constante, soit une prvalue expression constante fondamentale dont la valeur satisfait aux contraintes suivantes :

  • Si la valeur est un objet de type classe, chaque membre de données non statique de type référence se réfère à une entité qui est un résultat autorisé d'une expression constante.
  • Si la valeur est un objet de type scalaire , elle n'a pas de valeur indéterminée .
  • Si la valeur est de type pointeur , c'est l'une des valeurs suivantes :
  • l'adresse d'un objet avec durée de stockage statique
  • l'adresse après la fin d'un objet avec durée de stockage statique
  • l'adresse d'une fonction non immédiate (depuis C++20)
  • une valeur de pointeur nul
  • Si la valeur est de type pointeur-sur-fonction-membre, elle ne désigne pas une fonction immédiate.
(depuis C++20)
  • Si la valeur est un objet de type classe ou tableau, chaque sous-objet satisfait à ces contraintes pour la valeur.
(depuis C++14)
(jusqu'à C++26)

Une expression constante est soit une glvalue expression constante de base qui réfère à un objet ou une fonction non- immédiate , soit une prvalue expression constante de base dont la valeur satisfait les contraintes suivantes :

(depuis C++26)

Lors de la détermination si une expression est une expression constante, l'élision de copie est supposée ne pas être effectuée.

La définition C++98 des expressions constantes se trouve entièrement dans la boîte repliable. La description suivante s'applique à C++11 et aux versions ultérieures de C++.

Type littéral

Les types suivants sont collectivement appelés types littéraux :

  • Il possède un destructeur trivial (jusqu'en C++20) constexpr destructeur (depuis C++20) .
  • Tous ses membres de données non statiques non-variants et classes de base sont de types littéraux non-volatils.
  • C'est l'un des types suivants :
(depuis C++17)
  • un type union agrégé qui satisfait l'une des conditions suivantes :
  • Il n'a pas de membre variant .
  • Il a au moins un membre variant de type littéral non volatile.
  • Il n'a pas de membre variant.
  • Il a au moins un membre variant de type littéral non volatile.
  • un type avec au moins un constexpr constructeur (template) qui n'est pas un constructeur de copie ou de déplacement

Seuls les objets de types littéraux peuvent être créés dans une expression constante.

Expression constante de base

Une expression constante de base est toute expression dont l'évaluation ne devrait pas évaluer l'une quelconque des constructions de langage suivantes :

Constructe de langage Version Document(s)
le pointeur this , sauf dans une constexpr fonction évaluée dans le cadre de l'expression, ou lorsqu'il apparaît dans une expression d'accès membre de classe implicite ou explicite N2235
un flux de contrôle qui traverse une déclaration d'une variable de bloc avec une durée de stockage statique ou thread qui n'est pas utilisable dans les expressions constantes (depuis C++23) P2242R3
  1. a function call expression that calls a function (or a constructor) that is not declared constexpr
    constexpr int n = std::numeric_limits<int>::max(); // OK : max() est constexpr
    constexpr int m = std::time(nullptr); // Erreur : std::time() n'est pas constexpr
  2. a function call to a constexpr function which is declared, but not defined
  3. a function call to a constexpr function/constructor template instantiation where the instantiation fails to satisfy fonction/constructeur constexpr requirements.
  4. a function call to a constexpr virtual function, invoked on an object whose dynamic type is constexpr-unknown
  5. an expression that would exceed the implementation-defined limits
  6. an expression whose evaluation leads to any form of core language indéfini ou erroné (depuis C++26) behavior, except for any potential undefined behavior introduced by attributs standard .
    constexpr double d1 = 2.0 / 1.0; // OK
    constexpr double d2 = 2.0 / 0.0; // Erreur : non défini
    constexpr int n = std::numeric_limits<int>::max() + 1; // Erreur : dépassement
    int x, y, z[30];
    constexpr auto e1 = &y - &x;        // Erreur : indéfini
    constexpr auto e2 = &z[20] - &z[3]; // OK
    constexpr std::bitset<2> a; 
    constexpr bool b = a[2]; // Comportement indéfini, mais non spécifié si détecté
  7. (jusqu'à C++17) a expression lambda
  8. an lvalue-to-rvalue conversion implicite unless applied to...
    1. une glvalue de type (éventuellement qualifié cv) std::nullptr_t
    2. une glvalue de type littéral non volatile qui désigne un objet utilisable dans les expressions constantes
      int main()
      {
          const std::size_t tabsize = 50;
          int tab[tabsize]; // OK: tabsize est une expression constante
                            // car tabsize est utilisable dans les expressions constantes
                            // car il a un type intégral qualifié const, et
                            // son initialiseur est un initialiseur constant
          std::size_t n = 50;
          const std::size_t sz = n;
          int tab2[sz]; // Erreur: sz n'est pas une expression constante
                        // car sz n'est pas utilisable dans les expressions constantes
                        // car son initialiseur n'était pas un initialiseur constant
      }
    3. une glvalue de type littéral non volatile qui fait référence à un objet non volatile dont la durée de vie a commencé durant l'évaluation de cette expression
  9. an lvalue-to-rvalue conversion implicite or modification applied to a non-active member of a union or its subobject (even if it shares a common initial sequence with the active member)
  10. an lvalue-to-rvalue implicit conversion on an object dont la valeur est indéterminée
  11. an invocation of implicit copy/move constructor/assignment for a union whose active member is mutable (if any), with lifetime beginning outside the evaluation of this expression
  12. (jusqu'à C++20) an assignment expression that would change the active member of a union
  13. conversion from pointeur vers void to a pointer-to-object type T* sauf si le pointeur contient une valeur de pointeur nul ou pointe vers un objet dont le type est similaire à T (depuis C++26)
  14. dynamic_cast dont l'opérande est une glvalue qui fait référence à un objet dont le type dynamique est constexpr-inconnu (depuis C++20)
  15. reinterpret_cast
  16. (jusqu'à C++20) pseudo-destructor call
  17. (jusqu'à C++14) an increment or a decrement operator
  18. (depuis C++14) modification of an object, unless the object has non-volatile literal type and its lifetime began within the evaluation of the expression
    constexpr int incr(int& n)
    {
        return ++n;
    }
    constexpr int g(int k)
    {
        constexpr int x = incr(k); // Erreur : incr(k) n'est pas une expression constante de base
                                   // car la durée de vie de k
                                   // a commencé en dehors de l'expression incr(k)
        return x;
    }
    constexpr int h(int k)
    {
        int x = incr(k); // OK : x n'est pas requis d'être initialisé
                         // avec une expression constante de base
        return x;
    }
    constexpr int y = h(1); // OK : initialise y avec la valeur 2
                            // h(1) est une expression constante de base car
                            // la durée de vie de k commence à l'intérieur de l'expression h(1)
  19. (depuis C++20) a destructor call or pseudo destructor call for an object whose lifetime did not begin within the evaluation of this expression
  20. a typeid expression applied to a glvalue of polymorphic type et que cette glvalue fait référence à un objet dont le type dynamique est constexpr-inconnu (depuis C++20)
  21. a new expression , sauf si l'une des conditions suivantes est satisfaite : (depuis C++20)
    (depuis C++20)
    • La fonction d'allocation sélectionnée est une forme non-allouante avec un type alloué T , et l'argument de placement satisfait toutes les conditions suivantes :
    • Il pointe vers :
    • un objet dont le type est similaire à T , si T n'est pas un type tableau, ou
    • le premier élément d'un objet d'un type similaire à T , si T est un type tableau.
    • Il pointe vers un stockage dont la durée a commencé durant l'évaluation de cette expression.
    (depuis C++26)
  22. a delete expression , sauf s'il désalloue une région de mémoire allouée durant l'évaluation de cette expression (depuis C++20)
  23. (depuis C++20) Coroutines: an expression await or a expression-yield
  24. (depuis C++20) a comparaison à trois voies when the result is unspecified
  25. an equality or relational operator whose result is unspecified
  26. (jusqu'en C++14) an assignment or a compound assignment operator
  27. (jusqu'au C++26) une expression throw
  28. (depuis C++26) une construction d'un objet exception, sauf si l'objet exception et toutes ses copies implicites créées par les invocations de std::current_exception ou std::rethrow_exception sont détruits durant l'évaluation de cette expression
    constexpr void check(int i)
    {
        if (i < 0)
            throw i;
    }
    constexpr bool is_ok(int i)
    {
        try {
            check(i);
        } catch (...) {
            return false;
        }
        return true;
    }
    constexpr bool always_throw()
    {
        throw 12;
        return true;
    }
    static_assert(is_ok(5)); // OK
    static_assert(!is_ok(-1)); // OK depuis C++26
    static_assert(always_throw()); // Erreur : exception non capturée
  29. une déclaration asm
  30. une invocation de la macro va_arg
  31. une instruction goto
  32. une expression dynamic_cast ou typeid ou une expression new (depuis C++26) qui lancerait une exception où aucune définition du type d'exception n'est accessible (depuis C++26)
  33. dans une expression lambda, une référence à this ou à une variable définie à l'extérieur de cette lambda, si cette référence constituerait une odr-use
    void g()
    {
        const int n = 0;
        constexpr int j = *&n; // OK : en dehors d'une expression lambda
        [=]
        {
            constexpr int i = n;   // OK : 'n' n'est pas odr-used et n'est pas capturé ici
            constexpr int j = *&n; // Mal formé : '&n' serait une odr-use de 'n'
        };
    }

    notez que si l'odr-use a lieu dans un appel de fonction à une closure, il ne se réfère pas à this ou à une variable englobante, car il accède à un membre de données de la closure à la place

    // OK : 'v' & 'm' sont odr-used mais n'apparaissent pas dans une expression constante
    // dans la lambda imbriquée
    auto monad = [](auto v){ return [=]{ return v; }; };
    auto bind = [](auto m){ return [=](auto fvm){ return fvm(m()); }; };
    // OK d'avoir des captures vers des objets automatiques créés durant l'évaluation d'expression constante
    static_assert(bind(monad(2))(monad)() == monad(2)());
    (depuis C++17)

Exigences supplémentaires

Même si une expression E n'évalue rien de ce qui est mentionné ci-dessus, il est défini par l'implémentation si E est une expression constante de base si l'évaluation de E entraînerait un comportement indéfini à l'exécution .

Même si une expression E n'évalue rien de ce qui est mentionné ci-dessus, il n'est pas spécifié si E est une expression constante de base si l'évaluation de E évaluerait l'un des éléments suivants :

Pour déterminer si une expression est une expression constante de base, l'évaluation du corps d'une fonction membre de std:: allocator < T > est ignorée si T est un type littéral.

Aux fins de déterminer si une expression est une expression constante de base, l'évaluation d'un appel à un constructeur de copie/déplacement trivial ou à un opérateur d'affectation de copie/déplacement d'une union est considérée comme copiant/déplaçant le membre actif de l'union, s'il existe.

Pour déterminer si une expression est une expression constante de base, l'évaluation d'une expression d'identifiant qui nomme une liaison structurée bd a la sémantique suivante :

  • Si bd est une lvalue référençant l'objet lié à une référence inventée ref , le comportement est comme si ref était nommée.
  • Sinon, si bd nomme un élément de tableau, le comportement est celui de l'évaluation de e [ i ] , où e est le nom de la variable initialisée à partir de l'initialiseur de la déclaration de liaison structurée, et i est l'indice de l'élément référencé par bd .
  • Sinon, si bd nomme un membre de classe, le comportement est celui de l'évaluation de e. m , où e est le nom de la variable initialisée à partir de l'initialiseur de la déclaration de liaison structurée, et m est le nom du membre référencé par bd .
(depuis C++26)

Lors de l'évaluation de l'expression en tant qu'expression constante de base, toutes les expressions d'identificateur et les utilisations de * this qui se réfèrent à un objet ou une référence dont la durée de vie a commencé en dehors de l'évaluation de l'expression sont traitées comme se référant à une instance spécifique de cet objet ou de cette référence dont la durée de vie et celle de tous les sous-objets (y compris tous les membres d'union) inclut l'ensemble de l'évaluation constante.

  • Pour un tel objet qui n'est pas utilisable dans les expressions constantes (depuis C++20) , le type dynamique de l'objet est constexpr-unknown .
  • Pour une telle référence qui n'est pas utilisable dans les expressions constantes (depuis C++20) , la référence est traitée comme liée à un objet non spécifié du type référencé dont la durée de vie et celle de tous les sous-objets inclut l'ensemble de l'évaluation constante et dont le type dynamique est constexpr-unknown.

Expression constante entière

Expression constante entière est une expression de type entier ou de type énumération non-scopée implicitement convertie en prvalue, où l'expression convertie est une expression constante de base.

Si une expression de type classe est utilisée là où une expression constante intégrale est attendue, l'expression est implicitement convertie contextuellement en un type intégral ou énumération non délimitée.

Expression constante convertie

Une expression constante convertie de type T est une expression implicitement convertie vers le type T , où l'expression convertie est une expression constante, et la séquence de conversion implicite contient seulement :

(depuis C++17)

Et si une liaison de référence a lieu, elle ne peut être qu'une liaison directe .

Les contextes suivants nécessitent une expression constante convertie :

(depuis C++14)
(depuis C++26)

Une expression constante contextuellement convertie de type bool est une expression, contextuellement convertie en bool , où l'expression convertie est une expression constante et la séquence de conversion contient uniquement les conversions mentionnées ci-dessus.

Les contextes suivants nécessitent une expression constante convertie contextuellement de type bool :

(jusqu'en C++23)
(depuis C++17)
(jusqu'en C++23)
(depuis C++20)


Entités constitutives

Les valeurs constitutives d'un objet obj sont définies comme suit :

Les références constitutives d'un objet obj incluent les références suivantes :

  • tout membre direct de obj qui a un type référence
  • les références constitutives de tout sous-objet direct de obj autre que les membres inactifs d'union

Les valeurs constitutives et références constitutives d'une variable var sont définies comme suit :

  • Si var déclare un objet, les valeurs et références constitutives sont les valeurs et références constitutives de cet objet.
  • Si var déclare une référence, la référence constitutive est cette référence.

Pour toute référence constitutive ref d'une variable var , si ref est liée à un objet temporaire ou à un sous-objet de celui-ci dont la durée de vie est étendue à celle de ref , les valeurs et références constitutives de cet objet temporaire sont également des valeurs et références constitutives de var , récursivement.

Entités représentables en constexpr

Les objets avec une durée de vie statique sont référençables en constexpr à tout point du programme.

Un objet obj avec une durée de vie automatique est référençable en constexpr à partir d'un point P si la plus petite portée englobant la variable var et la plus petite portée englobant P sont la même portée de paramètre de fonction qui n'est pas associée à la liste de paramètres d'une requires expression , où var est la variable correspondant à l'objet complet de obj ou la variable à la durée de vie de laquelle celle de obj est étendue .

Un objet ou une référence x est représentable en constexpr à un point P si toutes les conditions suivantes sont satisfaites :

  • Pour chaque valeur constitutive de x qui pointe vers un objet obj , obj est référençable en constexpr à partir de P .
  • Pour chaque valeur constitutive de x qui pointe au-delà d'un objet obj , obj est référençable en constexpr à partir de P .
  • Pour chaque référence constitutive de x qui réfère à un objet obj , obj est référençable en constexpr à partir de P .
(depuis C++26)

Entités à initialisation constante

Une variable ou un objet temporaire obj est initialisé de manière constante si toutes les conditions suivantes sont satisfaites :

  • Soit il a un initialiseur, soit son type est const-default-constructible .
  • La expression complète de son initialisation est une expression constante dans le contexte nécessitant une expression constante, sauf que si obj est un objet, cette expression complète peut également invoquer des constexpr constructeurs pour obj et ses sous-objets même si ces objets sont de types de classe non littéraux.
(jusqu'à C++26)

Une variable var est initialisable de manière constante si toutes les conditions suivantes sont satisfaites :

  • La expression complète de son initialisation est une expression constante dans le contexte nécessitant une expression constante, où toutes les assertions de contrat utilisent la sémantique d'évaluation "ignorer".
  • Immédiatement après la déclaration d'initialisation de var , l'objet ou la référence déclaré(e) par var est représentable constexpr.
  • Si l'objet ou la référence x déclaré(e) par var a une durée de stockage statique ou thread, x est représentable constexpr au point le plus proche dont la portée immédiate est une portée d'espace de noms qui suit la déclaration d'initialisation de var .

Une variable initialisable de manière constante est initialisée de manière constante si soit elle a un initialiseur, soit son type est const-default-constructible .

(depuis C++26)

Utilisable dans les expressions constantes

Une variable est potentiellement-constante si elle est une constexpr variable ou si elle a un type référence ou un type entier ou énumération qualifié const non volatile.

Une variable potentiellement constante initialisée de manière constante var est utilisable dans les expressions constantes à un point P si la déclaration d'initialisation D de var est accessible depuis P et si l'une des conditions suivantes est satisfaite :

Un objet ou une référence est utilisable dans des expressions constantes à un point P s'il s'agit de l'une des entités suivantes :

  • une variable qui est utilisable dans des expressions constantes à P
  • un objet temporaire de type littéral qualifié const non volatile dont la durée de vie est étendue à celle d'une variable qui est utilisable dans des expressions constantes à P
  • un objet paramètre de modèle
  • un littéral de chaîne objet
  • un sous-objet non mutable de l'un des éléments ci-dessus
  • un membre référence de l'un des éléments ci-dessus
(jusqu'en C++26)

Un objet ou une référence est potentiellement utilisable dans des expressions constantes à un point P s'il s'agit de l'une des entités suivantes :

  • une variable qui est utilisable dans des expressions constantes à P
  • un objet temporaire de type littéral qualifié const non volatile dont la durée de vie est étendue à celle d'une variable qui est utilisable dans des expressions constantes à P
  • un objet paramètre de modèle
  • un littéral de chaîne objet
  • un sous-objet non mutable de l'un des éléments ci-dessus
  • un membre référence de l'un des éléments ci-dessus

Un objet ou une référence est utilisable dans des expressions constantes à un point P s'il s'agit d'un objet ou d'une référence qui est potentiellement utilisable dans des expressions constantes à P et qui est constexpr-représentable à P .

(depuis C++26)

Expressions manifestement évaluées de manière constante

Les expressions suivantes (y compris les conversions vers le type de destination) sont manifestement évaluées de manière constante :

Le fait qu'une évaluation se produise dans un contexte manifestement constant peut être détecté par std::is_constant_evaluated et if consteval (depuis C++23) .

(depuis C++20)

Fonctions et variables nécessaires pour l'évaluation constante

Les expressions ou conversions suivantes sont potentiellement évaluées de manière constante :

Une fonction est nécessaire pour l'évaluation constante si c'est une fonction constexpr et nommée par une expression potentiellement évaluée de manière constante.

Une variable est nécessaire pour l'évaluation constante si elle est soit une variable constexpr, soit de type intégral qualifié const non volatile ou de type référence, et que l' expression d'identifiant qui la désigne est potentiellement évaluée de manière constante.

Définition d'une fonction par défaut et instanciation d'une function template specialization ou variable template specialization (since C++14) sont déclenchées si la fonction ou variable (since C++14) est nécessaire pour l'évaluation constante.

Sous-expression constante

Une sous-expression constante est une expression dont l'évaluation en tant que sous-expression d'une expression e n'empêcherait pas e d'être une expression constante fondamentale , où e n'est aucune des expressions suivantes :

(depuis C++20)

Notes

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_constexpr_in_decltype 201711L (C++20)
(DR11)
Génération de définitions de fonctions et de variables lorsque nécessaire pour l'évaluation constante
__cpp_constexpr_dynamic_alloc 201907L (C++20) Opérations pour la durée de stockage dynamique dans les fonctions constexpr
__cpp_constexpr 202306L (C++26) constexpr cast depuis void * : vers l'effacement de type constexpr
202406L (C++26) constexpr placement new et new [ ]
__cpp_constexpr_exceptions 202411L (C++26) constexpr exceptions: [1] , [2]

Exemple

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement corrigé
CWG 94 C++98 les expressions constantes arithmétiques ne pouvaient pas
impliquer de variables et de membres de données statiques
elles le peuvent
CWG 366 C++98 les expressions impliquant des littéraux de chaîne
pourraient être des expressions constantes entières
elles ne le sont pas
CWG 457 C++98 les expressions impliquant des variables volatiles
pouvaient être des expressions constantes intégrales
elles ne le sont pas
CWG 1293 C++11 il n'était pas clair si les littéraux de chaîne
sont utilisables dans les expressions constantes
ils sont utilisables
CWG 1311 C++11 Les lvalues volatiles pouvaient être utilisées dans des expressions constantes interdit
CWG 1312 C++11 reinterpret_cast est interdit dans les expressions constantes,
mais un transtypage vers et depuis void * pourrait produire le même effet
conversions interdites
du type cv void * vers
un type pointeur-vers-objet
CWG 1313 C++11 le comportement indéfini était autorisé ;
toute soustraction de pointeurs était interdite
Comportement indéfini interdit ; soustraction
de pointeurs sur le même tableau autorisée
CWG 1405 C++11 pour les objets utilisables dans des expressions constantes,
leurs sous-objets mutables étaient également utilisables
ils ne sont pas utilisables
CWG 1454 C++11 le passage de constantes via des références dans des fonctions constexpr n'était pas autorisé
autorisé
autorisé
CWG 1455 C++11 les expressions constantes converties ne pouvaient être que des prvalues peuvent être des lvalues
CWG 1456 C++11 une expression constante d'adresse ne pouvait pas
désigner l'adresse juste après la fin d'un tableau
autorisé
CWG 1535 C++11 une typeid expression dont l'opérande est d'un
type de classe polymorphe n'était pas une expression constante
de base même si aucune vérification à l'exécution n'est impliquée
la contrainte sur l'opérande
est limitée aux glvalues de
types de classes polymorphes
CWG 1581 C++11 les fonctions nécessaires pour l'évaluation constante n'étaient
pas requises d'être définies ou instanciées
requis
CWG 1613 C++11 les expressions constantes de base pouvaient évaluer toute
référence utilisée par odr dans les expressions lambda
certaines références ne
pouvaient pas être évaluées
CWG 1694 C++11 lier la valeur d'un temporaire à une référence de durée de stockage
statique était une expression constante
ce n'est pas une
expression constante
CWG 1872 C++11 les expressions constantes principales pouvaient invoquer constexpr les instanciations de modèles de fonctions
qui ne satisfont pas aux exigences des fonctions constexpr
ces instanciations
ne peuvent pas être invoquées
CWG 1952 C++11 les comportements indéfinis de la bibliothèque standard
devaient être diagnostiqués
non spécifié si
ils sont diagnostiqués
CWG 2022 C++98 la détermination d'une expression constante pourrait
dépendre du fait que l'élision de copie soit effectuée
supposer que l'élision de copie
est toujours effectuée
CWG 2126 C++11 les temporaires à durée de vie prolongée par initialisation constante de types littéraux
qualifiés const n'étaient pas utilisables dans les expressions constantes
utilisable
CWG 2129 C++11 les littéraux entiers n'étaient pas des expressions constantes ils le sont
CWG 2167 C++11 références non-membres locales à une évaluation
rendaient l'évaluation non-constexpr
références non-membres
autorisées
CWG 2278 C++98 la résolution de CWG issue 2022 n'était pas implémentable supposer que l'élision de copie
n'est jamais effectuée
CWG 2299 C++14 il n'était pas clair si les macros dans <cstdarg>
pouvaient être utilisées lors de l'évaluation constante
va_arg interdit,
va_start non spécifié
CWG 2400 C++11 l'appel d'une fonction virtuelle constexpr sur un objet non utilisable
dans des expressions constantes et dont la durée de vie a commencé en dehors de
l'expression contenant l'appel pourrait être une expression constante
ce n'est pas une
expression constante
CWG 2490 C++20 Les appels de (pseudo) destructeurs manquaient
de restrictions lors de l'évaluation constante
restriction ajoutée
CWG 2552 C++23 lors de l'évaluation d'une expression constante de base, le flux de contrôle
ne pouvait pas passer par une déclaration d'une variable non-bloc
il peut
CWG 2558 C++11 une valeur indéterminée pourrait être une expression constante pas une expression constante
CWG 2647 C++20 les variables de types qualifiés volatile pourraient être potentiellement constantes elles ne le sont pas
CWG 2763 C++11 la violation de [[ noreturn ]] n'était pas requise
d'être détectée durant l'évaluation constante
requise
CWG 2851 C++11 les expressions constantes converties n'autorisaient
pas les conversions de nombres à virgule flottante
autoriser les conversions non-rétrécissantes
de nombres à virgule flottante
CWG 2907 C++11 les expressions constantes de base ne pouvaient pas appliquer
les conversions lvalue-vers-rvalue aux std::nullptr_t glvalues
peut appliquer de telles
conversions
CWG 2909 C++20 une variable sans initialiseur ne pouvait être
initialisée de manière constante que si son initialisation par défaut
entraîne l'exécution d'une certaine initialisation
ne peut être initialisée de manière constante
que si son type est
const-default-initializable
CWG 2924 C++11
C++23
il n'était pas spécifié si une expression violant
les contraintes de [[ noreturn ]] (C++11) ou
[[ assume ]] (C++23) est une expression constante de base
c'est
défini par l'implémentation
P2280R4 C++11 évaluer une expression contenant une expression d'identifiant
ou * this qui fait référence à un objet ou une référence dont la durée de vie
a commencé en dehors de cette évaluation n'est pas une expression constante
cela peut être une
expression constante

Voir aussi

constexpr spécificateur (C++11) spécifie que la valeur d'une variable ou fonction peut être calculée à la compilation
(C++11) (obsolète en C++17) (supprimé en C++20)
vérifie si un type est un type littéral
(modèle de classe)
Documentation C pour Expressions constantes