C++ constexpr Functions | Compile-Time Functions Explained

C++ constexpr Functions | Compile-Time Functions Explained

이 글의 핵심

Guide to constexpr functions: when they run at compile time, evolution across standards, and real-world patterns.

What is a constexpr function?

A function that can be used in compile-time and runtime contexts.

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

int main() {
    // compile time
    constexpr int a = square(5);  // 25
    
    // runtime
    int x = 10;
    int b = square(x);  // runtime evaluation
}

C++11 vs C++14 vs C++17

// C++11: often a single return statement
constexpr int factorial11(int n) {
    return n <= 1 ? 1 : n * factorial11(n - 1);
}

// C++14: multiple statements, loops
constexpr int factorial14(int n) {
    int result = 1;
    for (int i = 2; i <= n; i++) {
        result *= i;
    }
    return result;
}

// C++17: if constexpr for templates
template<typename T>
constexpr auto process(T value) {
    if constexpr (std::is_integral_v<T>) {
        return value * 2;
    } else {
        return value;
    }
}

Basic usage

constexpr int add(int a, int b) {
    return a + b;
}

constexpr int multiply(int a, int b) {
    return a * b;
}

constexpr int SIZE = add(10, 20);
int arr[SIZE];  // compile-time array size

Practical examples

Example 1: Math helpers

constexpr int fibonacci(int n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

constexpr int power(int base, int exp) {
    int result = 1;
    for (int i = 0; i < exp; i++) {
        result *= base;
    }
    return result;
}

constexpr bool isPrime(int n) {
    if (n <= 1) return false;
    if (n == 2) return true;
    if (n % 2 == 0) return false;
    for (int i = 3; i * i <= n; i += 2) {
        if (n % i == 0) return false;
    }
    return true;
}

int main() {
    constexpr int fib10 = fibonacci(10);
    constexpr int pow = power(2, 10);
    constexpr bool prime = isPrime(17);
    std::cout << fib10 << '\n' << pow << '\n' << prime << '\n';
}

Example 2: String helpers

constexpr size_t strlen_constexpr(const char* str) {
    size_t len = 0;
    while (str[len] != '\0') {
        len++;
    }
    return len;
}

constexpr bool startsWith(const char* str, const char* prefix) {
    while (*prefix != '\0') {
        if (*str != *prefix) return false;
        str++;
        prefix++;
    }
    return true;
}

int main() {
    constexpr size_t len = strlen_constexpr("Hello");
    constexpr bool starts = startsWith("Hello World", "Hello");
    char buffer[len + 1];
}

Example 3: Hash (illustrative)

constexpr unsigned int hash(const char* str) {
    unsigned int h = 5381;
    while (*str) {
        h = ((h << 5) + h) + *str;
        str++;
    }
    return h;
}

Example 4: Array generation

constexpr int generateValue(int index) {
    return index * index;
}

template<size_t N>
constexpr std::array<int, N> generateArray() {
    std::array<int, N> arr{};
    for (size_t i = 0; i < N; i++) {
        arr[i] = generateValue(i);
    }
    return arr;
}

int main() {
    constexpr auto arr = generateArray<10>();
    for (int x : arr) {
        std::cout << x << " ";
    }
}

constexpr classes

class Point {
    int x, y;
public:
    constexpr Point(int x, int y) : x(x), y(y) {}
    constexpr int getX() const { return x; }
    constexpr int getY() const { return y; }
    constexpr int distanceSquared() const { return x * x + y * y; }
};

int main() {
    constexpr Point p(3, 4);
    constexpr int dist = p.distanceSquared();
    int arr[dist];
}

Common issues

Calling non-constexpr functions

int nonConstexpr(int x) { return x * 2; }

// error if used in constexpr context
constexpr int bad(int x) {
    return nonConstexpr(x);
}

constexpr int good(int x) { return x * 2; }
constexpr int ok(int x) { return good(x); }

Virtual functions

C++20 allows more constexpr virtual scenarios; check your standard version for exact rules.

Runtime-only values

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

int main() {
    int runtime_value;
    std::cin >> runtime_value;
    int result = square(runtime_value);  // OK at runtime
}

constexpr vs const

const int x = getValue();     // initialized at runtime if needed
constexpr int y = 42;         // compile-time constant

Optimization

Heavy constexpr computation can fold entirely into constants in the object file (implementation-defined).

FAQ

Q: When to use constexpr? For compile-time constants, sizes, and generic code that must run at compile time when possible.

Q: Runtime use? Yes—constexpr functions are still normal functions when inputs are not constant expressions.

Q: Learning resources: Effective Modern C++, cppreference, C++ Templates: The Complete Guide.


  • constexpr lambda
  • Compile-time programming
  • if constexpr

Keywords

C++, constexpr, compile-time, C++11


Note on source

The repository had no cpp-constexpr.md; this English article is based on cpp-constexpr-function.md and saved as cpp-constexpr-en.md per your naming request.