Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Le mot clé constexpr a été introduit dans C++11 et amélioré dans C++14. Cela signifie expression constante. Comme const, cela peut être appliqué aux variables : une erreur du compilateur est générée lorsque du code tente de modifier la valeur. Contrairement à const, constexpr peut également être appliqué aux fonctions et aux constructeurs de classe.
constexpr indique que la valeur, ou la valeur de retour, est constante et, lorsque c’est possible, est calculée lors de la compilation.
Une valeur intégrale constexpr peut être utilisée partout où un entier const est requis, comme dans les arguments de modèle et les déclarations de tableau. Quand une valeur est calculée à la compilation plutôt qu’à l’exécution, cela peut aider votre programme à s’exécuter plus rapidement et à consommer moins de mémoire.
Pour limiter la complexité des calculs constants à la compilation, et leurs impacts potentiels sur le temps de compilation, la norme C++14 exige que les types dans les expressions constantes soient des types littéraux.
Syntaxe
constexprexpression constante del’identificateur= de type littéral;
constexpridentificateurde type littéral{constant-expression} ;
constexpridentificateurde type littéral(params) ;
constexprctor(params) ;
Paramètres
params
Un ou plusieurs paramètres, chacun devant être un type littéral et lui-même une expression constante.
Valeur retournée
Une variable ou une fonction constexpr doit retourner un type littéral.
Variables constexpr
La différence principale entre les variables const et constexpr est que l’initialisation d’une variable const peut être différée jusqu’à l’exécution. Une variable constexpr doit être initialisée au moment de la compilation. Toutes les constexpr variables sont const.
Une variable peut être déclarée avec
constexpr, si elle a un type de littéral et est initialisée. Si l’initialisation est effectuée par un constructeur, le constructeur doit être déclaré commeconstexpr.Une référence peut être déclarée comme
constexprlorsque ces deux conditions sont remplies : l’objet référencé est initialisé par une expression constante, et toutes les conversions implicites invoquées lors de l’initialisation sont également des expressions constantes.Toutes les déclarations d’une variable ou fonction
constexprdoivent comporter le spécificateurconstexpr.
constexpr float x = 42.0;
constexpr float y{108};
constexpr float z = exp(5, 3);
constexpr int i; // Error! Not initialized
int j = 0;
constexpr int k = j + 1; //Error! j not a constant expression
fonctionsconstexpr
Une fonction constexpr est une fonction dont la valeur de retour est calculable au moment de la compilation lorsque le code de consommation en a besoin. Le code consommant nécessite la valeur de retour au moment de la compilation pour initialiser une variable constexpr, ou pour fournir un argument de modèle non de type. Lorsque ses arguments sont des valeurs constexpr, une fonction constexpr produit une constante à la compilation. Si ses arguments constexpr ne sont pas des valeurs , ou si la valeur de retour n’est pas requise au moment de la compilation, la fonction appelée génère une valeur à l’exécution comme une fonction régulière. (Ce double comportement vous évite d’avoir à écrire constexpr et constexpr non versions, de la même fonction.)
Une fonction ou un constructeur constexpr est implicitement inline.
Les règles suivantes s’appliquent également aux fonctionsconstexpr :
Une fonction
constexprdoit accepter et retourner des types littéraux uniquement.Une fonction
constexprpeut être récursive.Avant C++20, une fonction
constexprne peut pas être virtuelle, et un constructeur ne peut pas être défini commeconstexprlorsque la classe englobante possède des classes de base virtuelles. En C++20 et versions ultérieures, une fonctionconstexprpeut être virtuelle. Visual Studio 2019 version 16.10 et les versions ultérieures prennent en charge les fonctionsconstexprvirtuelles lorsque vous spécifiez l’option de compilateur/std:c++20ou une version ultérieure.Le corps de la fonction peut être défini avec la valeur
= defaultou= delete.Le corps ne peut contenir aucune instruction
gotooutryblocs.Une spécialisation explicite d’un modèle non
constexprmodèle peut être déclarée avecconstexpr:Une spécialisation explicite d’un modèle
constexprne doit pas obligatoirement être déclarée avecconstexpr:
Les règles suivantes s’appliquent aux fonctions constexpr dans Visual Studio 2017 et versions ultérieures :
Il peut contenir des instructions
ifetswitch, ainsi que toutes les instructions de bouclage, notammentfor, lesforbasées sur des plages, leswhileet les do-while.Il peut contenir des déclarations de variables locales, mais la variable doit être initialisée. Il doit s’agir d’un type littéral et ne peut pas être
staticou thread-local. La variable déclarée localement n’est pas nécessaire pour êtreconstet peut muter.Une fonction membre
constexprnon-staticn’est pas nécessaire pour être implicitementconst.
constexpr float exp(float x, int n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp(x * x, n / 2) :
exp(x * x, (n - 1) / 2) * x;
}
Conseil
Dans le débogueur de Visual Studio, lors du débogage d’une version Debug non optimisée, vous pouvez savoir si une fonction constexpr est évaluée au moment de la compilation en plaçant un point d’arrêt à l’intérieur de celle-ci. Si le point d'arrêt est atteint, la fonction a été appelée à l'exécution. Si ce n’est pas le cas, la fonction a été appelée au moment de la compilation.
Extern constexpr
L’option de compilateur /Zc :externConstexpr entraîne l’application du compilateur de liaison externe aux variables déclarées à l’aide de extern constexpr. Dans les versions antérieures de Visual Studio, soit par défaut, soit lorsque /Zc:externConstexpr- est spécifié, Visual Studio applique un lien interne aux variables constexpr même lorsque le mot-clé extern est utilisé. L’option /Zc:externConstexpr est disponible à partir de la mise à jour 15.6 de Visual Studio 2017 et est désactivée par défaut. L’option /permissive- n’active pas /Zc :externConstexpr.
Exemple
L’exemple suivant montre constexpr variables et des fonctions , ainsi qu’un type défini par l’utilisateur(-trice). Notez que, dans la dernière instruction dans main(), la constexprfonction membreGetValue() est un appel d’exécution, car la valeur n’est pas requise par le code au moment de la compilation.
// constexpr.cpp
// Compile with: cl /EHsc /W4 constexpr.cpp
#include <iostream>
using namespace std;
// Pass by value
constexpr float exp(float x, int n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp(x * x, n / 2) :
exp(x * x, (n - 1) / 2) * x;
}
// Pass by reference
constexpr float exp2(const float& x, const int& n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp2(x * x, n / 2) :
exp2(x * x, (n - 1) / 2) * x;
}
// Compile-time computation of array length
template<typename T, int N>
constexpr int length(const T(&)[N])
{
return N;
}
// Recursive constexpr function
constexpr int fac(int n)
{
return n == 1 ? 1 : n * fac(n - 1);
}
// User-defined type
class Foo
{
public:
constexpr explicit Foo(int i) : _i(i) {}
constexpr int GetValue() const
{
return _i;
}
private:
int _i;
};
int main()
{
// foo is const:
constexpr Foo foo(5);
// foo = Foo(6); //Error!
// Compile time:
constexpr float x = exp(5, 3);
constexpr float y { exp(2, 5) };
constexpr int val = foo.GetValue();
constexpr int f5 = fac(5);
const int nums[] { 1, 2, 3, 4 };
const int nums2[length(nums) * 2] { 1, 2, 3, 4, 5, 6, 7, 8 };
// Run time:
cout << "The value of foo is " << foo.GetValue() << endl;
}
Spécifications
Visual Studio 2015 ou version ultérieure.