Menu
Coddy logo textTech

constexpr et consteval

Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 87 sur 104.

C++ permet d’effectuer des calculs au moment du compile plutôt qu’à l’exécution, ce qui peut améliorer considérablement les performances. Le mot-clé constexpr (C++11) et le mot-clé consteval (C++20) vous permettent de contrôler le moment où les expressions sont évaluées.

Une fonction constexpr peut être évaluée lors de la compilation si elle reçoit des arguments constants, mais elle peut également s’exécuter lors de l’exécution avec des entrées non constantes :

#include <iostream>

constexpr int square(int n) {
    return n * n;
}

int main() {
    constexpr int compileTime = square(5);  // Évalué à la compilation
    
    int x = 7;
    int runtime = square(x);  // Évalué à l'exécution
    
    std::cout << compileTime << "\n";  // 25
    std::cout << runtime << "\n";      // 49
}

Lorsque vous devez garantir une évaluation à la compilation, utilisez consteval. Une fonction consteval doit produire une constante : l’appeler avec des valeurs d’exécution provoque une erreur de compilation :

consteval int factorial(int n) {
    return n <= 1 ? 1 : n * factorial(n - 1);
}

int main() {
    constexpr int result = factorial(5);  // OK : 120 calculé à la compilation
    
    // int x = 5;
    // int bad = factorial(x);  // ERROR: x n'est pas une constante
}

Vous pouvez également utiliser constexpr avec des variables et même des constructeurs de classes, ce qui permet de créer des objets entiers lors de la compilation. Cela est particulièrement utile pour les tables de recherche, les valeurs de configuration ou toute donnée qui ne change pas pendant l’exécution du programme.

challenge icon

Défi

Facile

Vous organiserez votre code sur trois fichiers :

  • MathUtils.h : définissez vos fonctions mathématiques évaluées à la compilation.

    Créez les fonctions suivantes :

    • cube : une fonction constexpr qui prend un int et renvoie son cube (n * n * n)
    • triangularNumber : une fonction constexpr qui calcule le n-ième nombre triangulaire à l'aide de la formule n * (n + 1) / 2. Dans cette tâche, nous ne l'appelons que dans un contexte d'évaluation à la compilation, en stockant son résultat dans une variable constexpr.
    • sumOfSquares : une fonction constexpr qui prend deux entiers et renvoie la somme de leurs carrés (a*a + b*b)
  • Config.h : créez une structure de configuration à l'aide de constantes évaluées à la compilation.

    Définissez une structure Config avec un constructeur constexpr qui prend trois entiers : width, height et depth. Stockez-les comme membres publics. Ajoutez également une méthode constexpr appelée volume() qui renvoie width * height * depth.

    Sous la structure, créez une constante globale constexpr appelée DEFAULT_CONFIG, initialisée avec les valeurs 10, 20 et 5.

  • main.cpp : lisez deux entiers depuis l'entrée représentant des valeurs d'exécution.

    Commencez par démontrer l'évaluation à la compilation en créant des variables constexpr :

    • Stockez cube(4) dans une variable constexpr et affichez : Cube of 4: [value]
    • Stockez triangularNumber(10) dans une variable constexpr et affichez : 10th triangular number: [value]
    • Affichez le volume de la configuration par défaut : Default volume: [value]

    Ensuite, démontrez que les fonctions constexpr peuvent également fonctionner à l'exécution en utilisant vos deux valeurs d'entrée :

    • Appelez cube() avec la première entrée et affichez : Cube of [input]: [result]
    • Appelez sumOfSquares() avec les deux entrées et affichez : Sum of squares: [result]

Par exemple, avec les entrées 3 et 4 :

Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 3: 27
Sum of squares: 25

Avec les entrées 5 et 12 :

Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 5: 125
Sum of squares: 169

Essayez vous-même

#include <iostream>
#include "MathUtils.h"
#include "Config.h"

using namespace std;

int main() {
    // Lire deux entiers depuis l'entrée
    int input1, input2;
    cin >> input1;
    cin >> input2;
    
    // TODO: Démontrer l'évaluation à la compilation
    // Créer une variable constexpr stockant cube(4) et afficher : "Cube of 4: [value]"
    
    // TODO: Create a constexpr variable storing triangularNumber(10)
    // and print: "10th triangular number: [value]"
    
    // TODO: Print the default config's volume: "Default volume: [value]"
    
    // TODO: Démontrer l'utilisation à l'exécution des fonctions constexpr
    // Appeler cube() avec input1 et afficher : "Cube of [input1]: [result]"
    
    // TODO: Call sumOfSquares() with both inputs
    // and print: "Sum of squares: [result]"
    
    return 0;
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur C++ en ligne