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.

Le C++ permet d'effectuer des calculs au moment de la compilation 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 à la compilation si elle reçoit des arguments constants, mais elle peut également s'exécuter à 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 avez besoin de garantir l'évaluation au moment de la compilation, utilisez consteval. Une fonction consteval doit produire une constante - l'appeler avec des valeurs d'exécution est 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é au moment de la compilation
    
    // int x = 5;
    // int bad = factorial(x);  // ERREUR : x n'est pas une constante
}

Vous pouvez également utiliser constexpr avec des variables et même des constructeurs de classe, permettant à des objets entiers d'être créés au moment de la compilation. Ceci est particulièrement utile pour les tables de correspondance, 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 évaluables à la compilation.

    Créez les fonctions suivantes :

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

    Définissez une structure Config avec un constructeur constexpr qui prend trois entiers : width, height, et depth. Stockez-les en tant que membres publics. Ajoutez également une méthode constexpr appelée volume() qui retourne 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 à partir de l'entrée représentant des valeurs d'exécution.

    Tout d'abord, démontrez 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 au moment de la compilation
    // Créer une variable constexpr stockant cube(4) et afficher : "Cube of 4: [value]"
    
    // TODO : Créer une variable constexpr stockant triangularNumber(10)
    // et afficher : "10th triangular number: [value]"
    
    // TODO : Afficher le volume de la configuration par défaut : "Default volume: [value]"
    
    // TODO : Démontrer l'utilisation au moment de l'exécution des fonctions constexpr
    // Appeler cube() avec input1 et afficher : "Cube of [input1]: [result]"
    
    // TODO : Appeler sumOfSquares() avec les deux entrées
    // et afficher : "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