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 ocurran en tiempo de compilación en lugar de en tiempo de ejecución, lo que puede mejorar significativamente el rendimiento. La palabra clave constexpr (C++11) y la palabra clave consteval (C++20) le brindan control sobre cuándo se evalúan las expresiones.

Una función constexpr puede ser evaluada en tiempo de compilación si se le proporcionan 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);  // CORRECTO: 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 clase, permitiendo que se creen objetos enteros en tiempo de compilación. Esto es particularmente ú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 de tiempo de compilación.

    Crea las siguientes funciones:

    • cube — una función constexpr que toma un int y devuelve su cubo (n * n * n)
    • triangularNumber — una función constexpr que calcula el n-ésimo número triangular 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 toma dos enteros y devuelve la suma de sus cuadrados (a*a + b*b)
  • Config.h: Crea una estructura de configuración utilizando constantes de tiempo de compilación.

    Define una estructura Config con un constructor constexpr que tome tres enteros: width, height y depth. Almacénalos como miembros públicos. También añade 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 representan valores de 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 por defecto: Default volume: [value]

    Luego, 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() {
    // Leer dos enteros de la entrada
    int input1, input2;
    cin >> input1;
    cin >> input2;
    
    // TODO: Demostrar la evaluación en tiempo de compilación
    // Crear una variable constexpr que almacene cube(4) y mostrar: "Cube of 4: [value]"
    
    // TODO: Crear una variable constexpr que almacene triangularNumber(10)
    // y mostrar: "10th triangular number: [value]"
    
    // TODO: Mostrar el volumen de la configuración por defecto: "Default volume: [value]"
    
    // TODO: Demostrar el uso en tiempo de ejecución de funciones constexpr
    // Llamar a cube() con input1 y mostrar: "Cube of [input1]: [result]"
    
    // TODO: Llamar a sumOfSquares() con ambas entradas
    // y mostrar: "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