[2026] C++20 consteval Complete Guide | Immediate Functions and Compile-Time-Only Evaluation
이 글의 핵심
Master C++20 consteval: immediate functions for compile-time-only evaluation, validation, hashing, and zero-overhead configuration.
Why consteval Exists
Problem: constexpr Ambiguity
Problem: constexpr functions can execute at compile time or runtime. When you want to enforce compile-time computation, it’s ambiguous.
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 실행 예제
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
constexpr int x = factorial(5); // Compile-time: 120
int n = 10;
int y = factorial(n); // Runtime (may not be intended)
}
Solution: consteval is compile-time-only. Passing runtime values causes compile error, guaranteeing compile-time computation. 아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 실행 예제
consteval int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
constexpr int x = factorial(5); // OK: 120
int n = 10;
// int y = factorial(n); // Error: n is runtime value
}
아래 코드는 mermaid를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
flowchart TD
subgraph constexpr[constexpr]
ce1["Compile-time OK"]
ce2["Runtime OK"]
end
subgraph consteval[consteval]
cv1["Compile-time OK"]
cv2["Runtime Error"]
end
Table of Contents
- constexpr vs consteval
- Immediate Functions
- Practical Use: Compile-Time Validation
- Metaprogramming
- Common Errors and Solutions
- Production Patterns
- Complete Example: Compile-Time Config System
1. constexpr vs consteval
Comparison
| Aspect | constexpr | consteval |
|---|---|---|
| Compile-time execution | Possible | Required |
| Runtime execution | Possible | Not allowed |
| Purpose | Flexible computation | Compile-time guarantee |
| Error on runtime value | No | Yes |
Example
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// constexpr: both allowed
constexpr int add(int a, int b) {
return a + b;
}
int main() {
constexpr int x = add(1, 2); // Compile-time
int a = 5;
int y = add(a, 10); // Runtime (OK)
}
// consteval: compile-time only
consteval int multiply(int a, int b) {
return a * b;
}
int main() {
constexpr int x = multiply(2, 3); // OK
int a = 5;
// int y = multiply(a, 10); // Error: a is runtime value
}
Key: consteval enforces compile-time-only execution.
2. Immediate Functions
What are Immediate Functions?
consteval functions are immediate functions that must be immediately evaluated at call site.
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
consteval int square(int x) {
return x * x;
}
// consteval functions can only be called from consteval
consteval int sum_of_squares(int a, int b) {
return square(a) + square(b); // OK
}
// Cannot call from constexpr (if it might run at runtime)
constexpr int wrapper(int x) {
// return square(x); // Error: consteval in constexpr
return x * 2;
}
int main() {
constexpr int result = sum_of_squares(3, 4); // 25
}
Output:
25
Key: consteval functions can only be called from other consteval functions or constant expressions.
3. Practical Use: Compile-Time Validation
Range Validation
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
consteval int check_range(int value, int min, int max) {
if (value < min || value > max) {
throw "Value out of range";
}
return value;
}
int main() {
constexpr int size = check_range(100, 1, 1024); // OK
int buffer[size];
// constexpr int bad = check_range(2000, 1, 1024); // Compile error
}
Key: Compile-time validation prevents invalid configurations from compiling.
String Hashing
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <string_view>
consteval unsigned int hash(std::string_view str) {
unsigned int hash = 5381;
for (char c : str) {
hash = ((hash << 5) + hash) + static_cast<unsigned char>(c);
}
return hash;
}
enum class MessageType : unsigned int {
Login = hash("login"),
Logout = hash("logout"),
Data = hash("data")
};
void handle_message(const std::string& type) {
switch (hash(type.c_str())) { // Compile-time hash
case hash("login"):
std::cout << "Login\n";
break;
case hash("logout"):
std::cout << "Logout\n";
break;
case hash("data"):
std::cout << "Data\n";
break;
}
}
Key: Compile-time string hashing enables fast string-based switch statements.
Type Size Validation
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
template<typename T>
consteval bool is_small_type() {
return sizeof(T) <= 16;
}
template<typename T>
requires is_small_type<T>()
void process(T value) {
// T guaranteed to be 16 bytes or less
}
int main() {
process(42); // OK: sizeof(int) = 4
process(3.14); // OK: sizeof(double) = 8
// process(std::string{"hello"}); // Error: sizeof(string) > 16
}
Key: consteval predicates enable compile-time type constraints.
4. Metaprogramming
Compile-Time Factorial
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
consteval int factorial(int n) {
if (n < 0) throw "Negative factorial";
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
constexpr int f5 = factorial(5); // 120
constexpr int f10 = factorial(10); // 3628800
// Use as array size
int buffer[factorial(4)]; // 24 elements
}
Output:
// buffer has 24 elements
Compile-Time String Processing
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <array>
#include <string_view>
consteval std::size_t count_chars(std::string_view str, char c) {
std::size_t count = 0;
for (char ch : str) {
if (ch == c) ++count;
}
return count;
}
int main() {
constexpr auto count = count_chars("hello world", 'l');
static_assert(count == 3);
std::array<char, count> buffer; // 3 elements
}
Key: Compile-time string analysis for buffer sizing.
Compile-Time Configuration
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
consteval int get_buffer_size() {
#ifdef LARGE_BUFFER
return 1024 * 1024; // 1MB
#else
return 4096; // 4KB
#endif
}
consteval int get_thread_count() {
return 8; // Compile-time constant
}
int main() {
constexpr int buffer_size = get_buffer_size();
constexpr int threads = get_thread_count();
char buffer[buffer_size];
std::array<std::thread, threads> thread_pool;
}
Key: Build-time configuration without runtime overhead.
5. Common Errors and Solutions
Error 1: Passing Runtime Values
Symptom: error: call to consteval function is not a constant expression.
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
consteval int square(int x) {
return x * x;
}
int main() {
int a = 5;
// int b = square(a); // Error: a is runtime value
// ✅ Solution 1: constexpr variable
constexpr int c = 5;
int d = square(c); // OK
// ✅ Solution 2: literal
int e = square(5); // OK
}
Error 2: Side Effects
Symptom: error: call to non-constexpr function.
Cause: I/O, dynamic allocation, or other side effects in consteval function.
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ Wrong usage
consteval int bad() {
std::cout << "Hello\n"; // Error: I/O
return 42;
}
// ✅ Correct: pure computation only
consteval int good(int x) {
return x * 2;
}
Error 3: Calling consteval from constexpr
Cause: constexpr functions may run at runtime, so they cannot call consteval functions.
다음은 cpp를 활용한 상세한 구현 코드입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// 실행 예제
consteval int immediate() {
return 42;
}
// ❌ Wrong
constexpr int wrapper() {
return immediate(); // Error
}
// ✅ Correct: call from consteval
consteval int wrapper2() {
return immediate(); // OK
}
// ✅ Or use std::is_constant_evaluated()
constexpr int wrapper3(int x) {
if (std::is_constant_evaluated()) {
return 42; // Compile-time
} else {
return x * 2; // Runtime
}
}
Key: consteval can only be called from constant expressions or other consteval functions.
6. Production Patterns
Pattern 1: Compile-Time String Validation
다음은 cpp를 활용한 상세한 구현 코드입니다. 에러 처리를 통해 안정성을 확보합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
consteval bool is_valid_identifier(std::string_view str) {
if (str.empty()) return false;
if (!std::isalpha(str[0]) && str[0] != '_') return false;
for (char c : str) {
if (!std::isalnum(c) && c != '_') return false;
}
return true;
}
template<std::size_t N>
consteval auto make_identifier(const char (&str)[N]) {
if (!is_valid_identifier(str)) {
throw "Invalid identifier";
}
return std::string_view(str, N - 1);
}
int main() {
constexpr auto id1 = make_identifier("valid_name"); // OK
// constexpr auto id2 = make_identifier("123invalid"); // Compile error
}
Key: Enforce naming conventions at compile time.
Pattern 2: Compile-Time Lookup Tables
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <array>
consteval std::array<int, 256> generate_crc_table() {
std::array<int, 256> table{};
for (int i = 0; i < 256; ++i) {
int crc = i;
for (int j = 0; j < 8; ++j) {
crc = (crc >> 1) ^ ((crc & 1) ? 0xEDB88320 : 0);
}
table[i] = crc;
}
return table;
}
constexpr auto CRC_TABLE = generate_crc_table();
unsigned int crc32(const char* data, std::size_t length) {
unsigned int crc = 0xFFFFFFFF;
for (std::size_t i = 0; i < length; ++i) {
crc = (crc >> 8) ^ CRC_TABLE[(crc ^ data[i]) & 0xFF];
}
return ~crc;
}
Key: Pre-compute CRC tables at compile time for embedded systems.
Pattern 3: Configuration Calculation
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
consteval int calculate_pool_size() {
#ifdef PRODUCTION
return 128;
#elif defined(STAGING)
return 64;
#else
return 16;
#endif
}
consteval int calculate_timeout_ms() {
return 30 * 1000; // 30 seconds
}
int main() {
constexpr int pool_size = calculate_pool_size();
constexpr int timeout = calculate_timeout_ms();
static_assert(pool_size > 0);
static_assert(timeout > 0);
}
Key: Build-mode-dependent configuration without runtime checks.
7. Complete Example: Compile-Time Config System
다음은 cpp를 활용한 상세한 구현 코드입니다. 필요한 모듈을 import하고, 클래스를 정의하여 데이터와 기능을 캡슐화하며, 에러 처리를 통해 안정성을 확보합니다, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <string_view>
#include <array>
// Config key-value pair
struct ConfigEntry {
std::string_view key;
int value;
};
// Generate compile-time config
consteval auto generate_config() {
std::array<ConfigEntry, 3> config{{
{"max_connections", 1000},
{"timeout_ms", 30000},
{"buffer_size", 4096}
}};
return config;
}
// Compile-time config lookup
consteval int get_config(std::string_view key) {
constexpr auto config = generate_config();
for (const auto& entry : config) {
if (entry.key == key) {
return entry.value;
}
}
throw "Config key not found";
}
int main() {
constexpr int max_conn = get_config("max_connections"); // 1000
constexpr int timeout = get_config("timeout_ms"); // 30000
std::array<int, max_conn> connection_pool;
static_assert(max_conn == 1000);
static_assert(timeout == 30000);
}
Key: Type-safe compile-time configuration system with zero runtime overhead.
Advanced Patterns
Pattern 4: Compile-Time Bit Manipulation
아래 코드는 cpp를 사용한 구현 예제입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
consteval unsigned int reverse_bits(unsigned int n) {
unsigned int result = 0;
for (int i = 0; i < 32; ++i) {
result = (result << 1) | (n & 1);
n >>= 1;
}
return result;
}
constexpr unsigned int REVERSED = reverse_bits(0b10110000);
// REVERSED = 0b00001101 (compile-time)
Pattern 5: Compile-Time Prime Checking
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
consteval bool is_prime(int n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
template<int N>
requires is_prime(N)
class PrimeBuffer {
std::array<char, N> data;
};
int main() {
PrimeBuffer<17> buf1; // OK
// PrimeBuffer<16> buf2; // Error: 16 is not prime
}
Key: Compile-time constraints with requires and consteval.
Summary
Key Points
| Concept | Description |
|---|---|
| consteval | Compile-time-only functions |
| Immediate function | Evaluated immediately at call site |
| constexpr difference | consteval cannot run at runtime |
| Purpose | Compile-time validation, metaprogramming |
consteval enforces compile-time computation, enabling complex calculations with zero runtime overhead. |
FAQ
Q1: When to use consteval vs constexpr?
A: Use consteval to enforce compile-time computation; use constexpr for flexible compile-time or runtime execution.
Q2: Can I call consteval from constexpr?
A: No. consteval functions can only be called from consteval functions or constant expressions. constexpr functions may run at runtime, so calling consteval causes error.
Q3: What if I pass runtime values?
A: Compile error. consteval functions require all arguments to be compile-time constants.
Q4: What about side effects?
A: I/O, dynamic allocation, global variable modification, etc. are not allowed in consteval functions. Only pure computation.
Q5: Compiler support?
A:
- GCC 10+: Full support
- Clang 10+: Full support
- MSVC 2019 (16.10+): Full support
Q6: Learning resources?
A:
- cppreference - consteval
- “C++20: The Complete Guide” by Nicolai Josuttis
- Compile-time programming in C++20
Comparison: constexpr vs consteval vs const
| Feature | const | constexpr | consteval |
|---|---|---|---|
| Compile-time | Not guaranteed | Possible | Required |
| Runtime | Yes | Yes | No |
| Functions | No | Yes | Yes (C++20) |
| Variables | Yes | Yes | No (only functions) |
Example
다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// const: runtime constant
const int x = 10;
// constexpr: compile-time or runtime
constexpr int square(int n) { return n * n; }
// consteval: compile-time only
consteval int cube(int n) { return n * n * n; }
int main() {
int arr1[x]; // May work (implementation-defined)
constexpr int y = square(5);
int arr2[y]; // OK
constexpr int z = cube(3);
int arr3[z]; // OK
int runtime = 10;
int w = square(runtime); // OK (runtime)
// int v = cube(runtime); // Error (compile-time only)
}
Best Practices
1. Use consteval for Hard Compile-Time Requirements
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
// ✅ Enforce compile-time
consteval int config_value(int id) {
return id * 100;
}
constexpr int x = config_value(5); // OK
// int y = config_value(runtimeValue); // Error
2. Document Immediate Function Intent
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
/// @brief Compile-time-only hash function
/// @note Cannot be called with runtime values
consteval unsigned int hash(std::string_view str) {
// ...
}
3. Combine with static_assert
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다, 조건문으로 분기 처리를 수행합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
consteval int validate_config(int value) {
if (value <= 0) throw "Invalid config";
return value;
}
constexpr int POOL_SIZE = validate_config(128);
static_assert(POOL_SIZE == 128);
4. Avoid Deep Recursion
다음은 cpp를 활용한 상세한 구현 코드입니다. 반복문으로 데이터를 처리합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
// ❌ Deep recursion (slow compile)
consteval int fib(int n) {
return n <= 1 ? n : fib(n-1) + fib(n-2);
}
// ✅ Iterative (fast compile)
consteval int fib(int n) {
int a = 0, b = 1;
for (int i = 0; i < n; ++i) {
int temp = a + b;
a = b;
b = temp;
}
return a;
}
Related Articles
- C++ static_assert Guide
- C++20 Concepts Complete Guide
- C++ constexpr Functions
- C++ Compile-Time Programming Series #26-2
Keywords
C++20 consteval, immediate functions, compile-time-only, constexpr, metaprogramming, validation One-line summary: consteval enforces compile-time-only execution for immediate functions, enabling zero-overhead validation, hashing, and configuration systems.