Sobes.tech
Middle+

How are values computed at compile time in C/C++?

sobes.tech AI

Answer from AI

In C++, consteval and constexpr specifiers, as well as metaprogramming templates, are used to compute values at compile time. In C11+ for a limited set of expressions, the keyword const is used.

  • constexpr: Indicates that a variable or function may be evaluated at compile time. If all arguments are known at compile time, the compiler will attempt to perform the computation. If not, the computation will occur at runtime.

    // C++
    constexpr int factorial(int n) {
        return (n <= 1) ? 1 : n * factorial(n - 1);
    }
    
    int main() {
        // Compile-time computation
        constexpr int fact5 = factorial(5);
    
        // Runtime computation (if argument is not known at compile time)
        int runtime_val = 6;
        int fact_runtime = factorial(runtime_val);
    
        return 0;
    }
    
  • consteval: (C++20) Indicates that a function must be evaluated at compile time. Calling such a function in a context where the result cannot be computed at compile time will result in a compilation error.

    // C++20
    consteval int compile_time_add(int a, int b) {
        return a + b;
    }
    
    int main() {
        // OK: Compile-time evaluation
        constexpr int sum = compile_time_add(10, 20);
    
        // Compilation error: argument not known at compile time
        // int runtime_val = 5;
        // int sum_runtime = compile_time_add(sum, runtime_val);
    
        return 0;
    }
    
  • Metaprogramming templates: Use template instantiation to perform computations at compile time. Most often used for recursive calculations and type generation.

    // C++
    // Calculating factorial using templates
    template<int N>
    struct Factorial {
        static const int value = N * Factorial<N - 1>::value;
    };
    
    template<>
    struct Factorial<0> {
        static const int value = 1;
    };
    
    int main() {
        // Compile-time calculation via template instantiation
        constexpr int fact6 = Factorial<6>::value;
    
        return 0;
    }
    
  • const: In C11 and later versions of C, variables declared with const and initialized with a constant expression can be used in contexts requiring compile-time constants (e.g., static array sizes).

    // C11+
    const int array_size = 10; // Constant expression
    int static_array[array_size]; // OK in C11+
    
    // In C++, this has always been possible for const with a constant initializer.
    

Compile-time evaluation allows:

  • Improving performance by avoiding runtime code execution.
  • Making code safer by catching calculation errors (e.g., division by zero) at compile time.
  • Using computed values in contexts requiring constants (array sizes, template arguments, etc.).