C++ constexpr if | 'Compile-Time Branching' Guide
이 글의 핵심
C++17 if constexpr is a conditional statement evaluated only at compile-time within templates. Used with constexpr functions and constant initialization, can handle branching with type_traits in one function instead of template specialization.
Introduction
C++17 if constexpr is a conditional statement evaluated only at compile-time within templates. When branching with type_traits, can handle in one function instead of template specialization.
#include <iostream>
#include <type_traits>
// Template function: can accept any type T
template<typename T>
void process(T value) {
// if constexpr: evaluate condition at compile-time
// Only selected branch is generated as code (rest is removed)
// std::is_integral_v<T>: check if T is integer type
// (int, long, short, char, etc.)
if constexpr (std::is_integral_v<T>) {
std::cout << "Integer: " << value << std::endl;
}
// std::is_floating_point_v<T>: check if T is floating-point type
// (float, double, long double)
else if constexpr (std::is_floating_point_v<T>) {
std::cout << "Float: " << value << std::endl;
}
// Other types (string, pointer, etc.)
else {
std::cout << "Other: " << value << std::endl;
}
}
int main() {
process(42); // T=int → only first branch compiled
process(3.14); // T=double → only second branch compiled
process("hello"); // T=const char* → only third branch compiled
}
Output:
Integer
Integer: 43
Other
1. Regular if vs constexpr if
Comparison Table
| Aspect | Regular if | constexpr if |
|---|---|---|
| Evaluation time | Runtime | Compile-time |
| Condition | Runtime value | Compile-time constant |
| Code generation | All branches generated | Only selected branch |
| Type checking | All branches checked | Only selected branch |
| Optimization | Compiler-dependent | Guaranteed |
| Usage location | Anywhere | Mainly templates |
Code Generation Difference
#include <iostream>
#include <type_traits>
// Regular if: runtime evaluation
template<typename T>
void func1(T value) {
// Regular if: evaluate condition at runtime
// Problem: all branches must compile
if (std::is_integral_v<T>) { // Runtime
// value++; // ❌ Compile error!
// If T is string, value++ is invalid code
// Must compile even if not executed
std::cout << "Integer" << std::endl;
}
}
// constexpr if: compile-time evaluation
template<typename T>
void func2(T value) {
// if constexpr: evaluate condition at compile-time
// Only selected branch is compiled
if constexpr (std::is_integral_v<T>) { // Compile-time
// Only this code compiled if T is integer
value++; // ✅ OK (this code itself removed if T is string)
std::cout << "Integer: " << value << std::endl;
} else {
// Only this code compiled if T is not integer
std::cout << "Not integer" << std::endl;
}
}
int main() {
func1(42); // Runtime branch
func1(std::string("test")); // Runtime branch
func2(42); // Compile-time: only first branch generated
func2(std::string("test")); // Compile-time: only second branch generated
return 0;
}
2. Replacing Template Specialization
Implementation Comparison
| Item | Template Specialization | constexpr if |
|---|---|---|
| Lines of code | Many (function per type) | Few (one function) |
| Maintenance | Difficult | Easy |
| Readability | Scattered | Concentrated |
| Compile time | Slow | Fast |
| Debugging | Difficult | Easy |
#include <iostream>
#include <type_traits>
// ❌ Template specialization (complex)
template<typename T>
void print(T value);
template<>
void print<int>(int value) {
std::cout << "int: " << value << std::endl;
}
template<>
void print<double>(double value) {
std::cout << "double: " << value << std::endl;
}
template<>
void print<const char*>(const char* value) {
std::cout << "string: " << value << std::endl;
}
// ✅ constexpr if (simple)
template<typename T>
void printModern(T value) {
if constexpr (std::is_same_v<T, int>) {
std::cout << "int: " << value << std::endl;
} else if constexpr (std::is_same_v<T, double>) {
std::cout << "double: " << value << std::endl;
} else if constexpr (std::is_same_v<T, const char*>) {
std::cout << "string: " << value << std::endl;
} else {
std::cout << "other: " << value << std::endl;
}
}
int main() {
std::cout << "=== Template Specialization ===" << std::endl;
print(42);
print(3.14);
print("hello");
std::cout << "\n=== constexpr if ===" << std::endl;
printModern(42);
printModern(3.14);
printModern("world");
return 0;
}
Summary
Key Points
- if constexpr: C++17 compile-time conditional
- Code generation: Only selected branch generated
- Template simplification: Replaces template specialization
- Type traits: Powerful with type_traits
- Zero overhead: No runtime cost
When to Use
✅ Use if constexpr when:
- Template metaprogramming
- Type-dependent branching
- Replacing template specialization
- Compile-time optimization
❌ Don’t use when:
- Regular runtime conditions
- Non-template code
- Simple cases (overkill)
Best Practices
- ✅ Use with type_traits
- ✅ Simplify template code
- ✅ Reduce code duplication
- ❌ Don’t overuse (readability matters)
- ❌ Don’t use for runtime conditions
Related Articles
Master compile-time branching with if constexpr! 🚀
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. C++17 if constexpr is a conditional statement evaluated only at compile-time within templates.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.
Q. 더 깊이 공부하려면?
A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ Constant Initialization | ‘상수 초기화’ 가이드
- C++ 컴파일 타임 프로그래밍 | constexpr·consteval·if constexpr 완벽 가이드
- C++ constexpr Lambda | ‘컴파일 타임 람다’ 가이드
이 글에서 다루는 키워드 (관련 검색어)
C++, constexpr, if constexpr, compile-time, template 등으로 검색하시면 이 글이 도움이 됩니다.