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.
Sfida
FacileOrganizzerai il tuo codice in tre file:
MathUtils.h: Definisci le tue funzioni matematiche valutate in fase di compilazione.Crea le seguenti funzioni:
cube: una funzioneconstexprche accetta uninte restituisce il suo cubo (n * n * n)triangularNumber: una funzioneconstexprche 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 variabileconstexpr.sumOfSquares: una funzioneconstexprche 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
Configcon un costruttoreconstexprche accetta tre interi:width,heightedepth. Memorizzali come membri pubblici. Aggiungi anche un metodoconstexprchiamatovolume()che restituisce width * height * depth.Sotto la struct, crea una costante globale
constexprchiamataDEFAULT_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
constexprpossono 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]
- Memorizza
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: 25Con gli input 5 e 12:
Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 5: 125
Sum of squares: 169Provalo 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;
}
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
1Fondamenti della programmazione orientata agli oggetti
File esterniBuild e compilazione in C++File header e file sorgenteNamespace e ambitoIntroduzione alla programmazione orientata agli oggetti in C++Classi e oggetti a confrontoIl puntatore 'this'Metodi (funzioni membro)Attributi (membri dati)Fondamenti di costruttori e distruttoriRiepilogo - Calcolatrice semplice4Proprietà delle classi
Membri di istanza e staticiGetter e setterFunzioni membro constParola chiave mutableMetodi e variabili staticiFunzioni e classi friendRiepilogo - Gestore di conti bancari7Ereditarietà
Ereditarietà di baseLivelli di accesso nell’ereditarietàOrdine di chiamata di costruttori e distruttoriRidefinizione dei metodiFunzioni virtuali e VTableEreditarietà multiplaEreditarietà virtualeRiepilogo - Gerarchia dei dipendenti2Gestione della memoria
Memoria Stack vs HeapPuntatori e riferimentiMemoria dinamica (new/delete)Puntatori intelligenti in C++RAII in C++Riepilogo - Gestore di array dinamico5Incapsulamento
Specificatori di accesso in C++Specificatori di accesso in dettaglioOccultamento delle informazioniStruct vs classClassi annidate e interneRiepilogo - Sistema di registrazione degli studenti8Polimorfismo
Polimorfismo a compile time e a runtimeOverload delle funzioniFunzioni virtuali: ripassoFunzioni virtuali pureClassi astratteProgettazione delle interfacce in C++Dynamic casting e RTTIRipasso: calcolatrice di forme11Concetti avanzati di OOP
Composizione vs ereditarietàMixin tramite CRTPIdiom PimplType ErasureEnum class e tipizzazione forteGestione delle eccezioni in OOPGerarchie personalizzate di eccezioni14Pattern di progettazione - Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositeRAII come pattern3Costruttori e distruttori
Costruttore predefinitoCostruttore con parametriCostruttore di copiaCostruttore di spostamentoListe di inizializzazione dei costruttoriCostruttori delegantiApprofondimento sui distruttoriRegola del Tre / Cinque / ZeroRipasso - classe String6Sovraccarico degli operatori
Introduzione al sovraccarico degli operatoriSovraccarico degli operatori aritmeticiSovraccarico degli operatori di confrontoOperatori di flussoSovraccarico dell'operatore di assegnazioneSovraccarico degli operatori [] e ()Operatori di conversione di tipoRipasso - Classe Matrix9Template
Template di funzioneTemplate di classeSpecializzazione dei templateTemplate variadiciBasi di SFINAE e dei trait di tipoRiepilogo - Contenitore generico12Funzionalità moderne di C++
Semantica di spostamento e rvaluePerfect forwardingEspressioni lambda in dettagliostd::function e std::bindconstexpr e constevalStructured bindingsoptional, variant, anyEsercitati da solo: Compilatore C++ online