Menu
Coddy logo textTech

constexpr y consteval

Parte de la sección Programación Orientada a Objetos del Journey de C++ de Coddy. Lección 87 de 104.

C++ permite que los cálculos se realicen en tiempo de compilación en lugar de durante la ejecución, lo que puede mejorar significativamente el rendimiento. La palabra clave constexpr (C++11) y la palabra clave consteval (C++20) te permiten controlar cuándo se evalúan las expresiones.

Una función constexpr puede evaluarse en tiempo de compilación si recibe argumentos constantes, pero también puede ejecutarse en tiempo de ejecución con entradas no constantes:

#include <iostream>

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

int main() {
    constexpr int compileTime = square(5);  // Evaluado en tiempo de compilación
    
    int x = 7;
    int runtime = square(x);  // Evaluado en tiempo de ejecución
    
    std::cout << compileTime << "\n";  // 25
    std::cout << runtime << "\n";      // 49
}

Cuando necesites garantizar la evaluación en tiempo de compilación, usa consteval. Una función consteval debe producir una constante; llamarla con valores en tiempo de ejecución es un error de compilación:

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

int main() {
    constexpr int result = factorial(5);  // OK: 120 calculado en tiempo de compilación
    
    // int x = 5;
    // int bad = factorial(x);  // ERROR: x no es una constante
}

También puedes usar constexpr con variables e incluso constructores de clases, lo que permite crear objetos completos en tiempo de compilación. Esto es especialmente útil para tablas de búsqueda, valores de configuración o cualquier dato que no cambie durante la ejecución del programa.

challenge icon

Desafío

Fácil

Organizarás tu código en tres archivos:

  • MathUtils.h: Define tus funciones matemáticas evaluables en tiempo de compilación.

    Crea las siguientes funciones:

    • cube: una función constexpr que recibe un int y devuelve su cubo (n * n * n)
    • triangularNumber: una función constexpr que calcula el número triangular n usando la fórmula n * (n + 1) / 2. En esta tarea solo la llamaremos en un contexto de tiempo de compilación, almacenando su resultado en una variable constexpr.
    • sumOfSquares: una función constexpr que recibe dos enteros y devuelve la suma de sus cuadrados (a*a + b*b)
  • Config.h: Crea una estructura de configuración usando constantes de tiempo de compilación.

    Define una estructura Config con un constructor constexpr que recibe tres enteros: width, height y depth. Almacénalos como miembros públicos. Añade también un método constexpr llamado volume() que devuelva width * height * depth.

    Debajo de la estructura, crea una constante global constexpr llamada DEFAULT_CONFIG, inicializada con los valores 10, 20 y 5.

  • main.cpp: Lee dos enteros de la entrada que representen valores en tiempo de ejecución.

    Primero, demuestra la evaluación en tiempo de compilación creando variables constexpr:

    • Almacena cube(4) en una variable constexpr e imprime: Cube of 4: [value]
    • Almacena triangularNumber(10) en una variable constexpr e imprime: 10th triangular number: [value]
    • Imprime el volumen de la configuración predeterminada: Default volume: [value]

    Después, demuestra que las funciones constexpr también pueden funcionar en tiempo de ejecución usando tus dos valores de entrada:

    • Llama a cube() con la primera entrada e imprime: Cube of [input]: [result]
    • Llama a sumOfSquares() con ambas entradas e imprime: Sum of squares: [result]

Por ejemplo, con las entradas 3 y 4:

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

Con las entradas 5 y 12:

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

Pruébalo tú mismo

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

using namespace std;

int main() {
    // Lee dos enteros de la entrada
    int input1, input2;
    cin >> input1;
    cin >> input2;
    
    // TODO: Demuestra la evaluación en tiempo de compilación
    // Crea una variable constexpr que almacene cube(4) e imprime: "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: Demuestra el uso en tiempo de ejecución de funciones constexpr
    // Llama a cube() con input1 e imprime: "Cube of [input1]: [result]"
    
    // TODO: Call sumOfSquares() with both inputs
    // and print: "Sum of squares: [result]"
    
    return 0;
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C++ online