Menu
Coddy logo textTech

constexpr e consteval

Fa parte della sezione Programmazione orientata agli oggetti del percorso C++ di Coddy. Lezione 87 di 104.

C++ consente di eseguire i calcoli in fase di compilazione anziché a runtime, migliorando notevolmente le prestazioni. La parola chiave constexpr (C++11) e la parola chiave consteval (C++20) ti permettono di controllare quando vengono valutate le espressioni.

Una funzione constexpr può essere valutata in fase di compilazione se riceve argomenti costanti, ma può anche essere eseguita in fase di runtime con input non costanti:

#include <iostream>

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

int main() {
    constexpr int compileTime = square(5);  // Evaluated at compile time
    
    int x = 7;
    int runtime = square(x);  // Evaluated at runtime
    
    std::cout << compileTime << "\n";  // 25
    std::cout << runtime << "\n";      // 49
}

Quando hai bisogno di garantire la valutazione in fase di compilazione, usa consteval. Una funzione consteval deve produrre una costante: chiamarla con valori di runtime è un errore di compilazione:

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

int main() {
    constexpr int result = factorial(5);  // OK: 120 calcolato in fase di compilazione
    
    // int x = 5;
    // int bad = factorial(x);  // ERROR: x non è una costante
}

Puoi anche usare constexpr con le variabili e persino con i costruttori di classi, consentendo di creare interi oggetti in fase di compilazione. Ciò è particolarmente utile per le tabelle di ricerca, i valori di configurazione o qualsiasi dato che non cambia durante l'esecuzione del programma.

challenge icon

Sfida

Facile

Organizzerai il tuo codice in tre file:

  • MathUtils.h: Definisci le tue funzioni matematiche valutate in fase di compilazione.

    Crea le seguenti funzioni:

    • cube: una funzione constexpr che accetta un int e restituisce il suo cubo (n * n * n)
    • triangularNumber: una funzione constexpr che calcola l’ennesimo numero triangolare usando la formula n * (n + 1) / 2. In questo esercizio la chiamiamo solo in un contesto di compilazione, memorizzando il risultato in una variabile constexpr.
    • sumOfSquares: una funzione constexpr che accetta due interi e restituisce la somma dei loro quadrati (a*a + b*b)
  • Config.h: Crea una struttura di configurazione usando costanti valutate in fase di compilazione.

    Definisci una struct Config con un costruttore constexpr che accetta tre interi: width, height e depth. Memorizzali come membri pubblici. Aggiungi anche un metodo constexpr chiamato volume() che restituisce width * height * depth.

    Sotto la struct, crea una costante globale constexpr chiamata DEFAULT_CONFIG, inizializzata con i valori 10, 20 e 5.

  • main.cpp: Leggi due interi dall’input che rappresentano valori a runtime.

    Per prima cosa, mostra la valutazione in fase di compilazione creando variabili constexpr:

    • Memorizza cube(4) in una variabile constexpr e stampa: Cube of 4: [value]
    • Memorizza triangularNumber(10) in una variabile constexpr e stampa: 10th triangular number: [value]
    • Stampa il volume della configurazione predefinita: Default volume: [value]

    Poi, mostra che le funzioni constexpr possono funzionare anche a runtime usando i due valori di input:

    • Chiama cube() con il primo valore di input e stampa: Cube of [input]: [result]
    • Chiama sumOfSquares() con entrambi i valori di input e stampa: Sum of squares: [result]

Per esempio, con gli input 3 e 4:

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

Con gli input 5 e 12:

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

Provalo tu

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

using namespace std;

int main() {
    // Leggi due numeri interi dall'input
    int input1, input2;
    cin >> input1;
    cin >> input2;
    
    // TODO: Mostra la valutazione in fase di compilazione
    // Crea una variabile constexpr che memorizzi cube(4) e stampa: "Cube of 4: [value]"
    
    // TODO: Crea una variabile constexpr che memorizzi triangularNumber(10)
    // e stampa: "10th triangular number: [value]"
    
    // TODO: Stampa il volume della configurazione predefinita: "Default volume: [value]"
    
    // TODO: Mostra l'uso delle funzioni constexpr durante l'esecuzione
    // Chiama cube() con input1 e stampa: "Cube of [input1]: [result]"
    
    // TODO: Chiama sumOfSquares() con entrambi gli input
    // e stampa: "Sum of squares: [result]"
    
    return 0;
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore C++ online