← SEARCHABLE ARCHIVE
C / C++ · 2026-08-11

C++ de los fundamentos al dominio — Lección 17

Calcular en tiempo de compilación con constexpr y consteval

INTERACTIVE READING MODE →

Los artículos de este blog se han escrito con fines didácticos. Pueden contener errores; contrasta la información con el compilador y la biblioteca estándar de tu plataforma.

C++ puede ejecutar determinados cálculos antes de iniciar el programa. constexpr, consteval y constinit expresan contratos distintos: evaluación constante, llamada obligatoria en compilación e inicialización estática.

constexpr funciona en dos contextos

constexpr int Square(int value)
{
    return value * value;
}

constexpr int tableSize = Square(8); // compilación
int input = ReadInput();
int result = Square(input);          // ejecución

Una función constexpr puede evaluarse como constante, pero no todas sus llamadas tienen que ocurrir al compilar. Si los argumentos son constantes y el resultado se usa donde se exige una constant expression, el compilador debe evaluarla allí.

consteval obliga a evaluar al compilar

consteval unsigned int HashLiteral(std::string_view text)
{
    unsigned int hash = 2166136261u;
    for (char ch : text)
        hash = (hash ^ static_cast<unsigned char>(ch)) * 16777619u;
    return hash;
}

constexpr auto playerId = HashLiteral("Player");

Cada llamada a consteval debe ser una constant expression. Es útil para claves de recursos o etiquetas de protocolo fijadas durante el build.

Un hash todavía puede colisionar. Calcularlo en compilación no garantiza unicidad; siguen haciendo falta una política de colisiones y la validación de la clave original.

Eliminar una rama con if constexpr

template <typename T>
void Serialize(const T& value, Writer& writer)
{
    if constexpr (std::integral<T>)
        writer.WriteInteger(value);
    else
        value.Serialize(writer);
}

A diferencia de un if normal, la rama no seleccionada se descarta para esa instancia. Las operaciones inexistentes para el tipo elegido no necesitan ser válidas en la otra rama.

constinit comprueba la inicialización estática

constinit int globalLimit = 64;

constinit verifica la inicialización estática de un objeto con static storage duration. No lo vuelve inmutable; esa es la función de const.

El cálculo en compilación puede reducir inicialización en ejecución y detectar fallos antes, pero aumenta el tiempo de build, la complejidad de diagnósticos y a veces el tamaño binario. Úsalo cuando la regla sea realmente fija y la validación temprana compense el coste.