C++ constexpr 함수 | "컴파일 타임 함수" 가이드
이 글의 핵심
C++ constexpr 함수에 대해 정리한 개발 블로그 글입니다. constexpr int square(int x) { return x * x; }
constexpr 함수란?
컴파일 타임과 런타임 모두 사용 가능한 함수
constexpr int square(int x) {
return x * x;
}
int main() {
// 컴파일 타임
constexpr int a = square(5); // 25 (컴파일 시 계산)
// 런타임
int x = 10;
int b = square(x); // 런타임 계산
}
C++11 vs C++14 vs C++17
// C++11: 단일 return문만
constexpr int factorial11(int n) {
return n <= 1 ? 1 : n * factorial11(n - 1);
}
// C++14: 일반 함수처럼
constexpr int factorial14(int n) {
int result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
}
// C++17: if constexpr 추가
template<typename T>
constexpr auto process(T value) {
if constexpr (std::is_integral_v<T>) {
return value * 2;
} else {
return value;
}
}
기본 사용법
// 간단한 계산
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]; // 컴파일 타임 크기
실전 예시
예시 1: 수학 함수
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); // 55 (컴파일 타임)
constexpr int pow = power(2, 10); // 1024
constexpr bool prime = isPrime(17); // true
std::cout << fib10 << std::endl;
std::cout << pow << std::endl;
std::cout << prime << std::endl;
}
예시 2: 문자열 처리
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"); // 5
constexpr bool starts = startsWith("Hello World", "Hello"); // true
char buffer[len + 1]; // 컴파일 타임 크기
}
예시 3: 해시 함수
constexpr unsigned int hash(const char* str) {
unsigned int hash = 5381;
while (*str) {
hash = ((hash << 5) + hash) + *str;
str++;
}
return hash;
}
int main() {
// 컴파일 타임 해시
constexpr unsigned int h1 = hash("apple");
constexpr unsigned int h2 = hash("banana");
// switch문에 사용
const char* fruit = "apple";
switch (hash(fruit)) {
case hash("apple"):
std::cout << "사과" << std::endl;
break;
case hash("banana"):
std::cout << "바나나" << std::endl;
break;
}
}
예시 4: 배열 초기화
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>();
// arr = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
for (int x : arr) {
std::cout << x << " ";
}
}
constexpr 클래스
class Point {
private:
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(); // 25
int arr[dist]; // 컴파일 타임 크기
}
자주 발생하는 문제
문제 1: 비constexpr 함수 호출
int nonConstexpr(int x) {
return x * 2;
}
// ❌ 비constexpr 함수 호출
constexpr int func(int x) {
return nonConstexpr(x); // 에러
}
// ✅ constexpr 함수만 호출
constexpr int constexprFunc(int x) {
return x * 2;
}
constexpr int func(int x) {
return constexprFunc(x); // OK
}
문제 2: 정적 변수
// ❌ 정적 변수 (C++11)
constexpr int func() {
static int count = 0; // 에러
return count++;
}
// ✅ C++14부터 허용
constexpr int func14() {
static int count = 0; // OK (C++14)
return count++;
}
문제 3: 가상 함수
class Base {
public:
// ❌ constexpr 가상 함수 (C++17 이전)
virtual constexpr int getValue() const {
return 42;
}
};
// C++20부터 허용
class Base {
public:
virtual constexpr int getValue() const {
return 42;
}
};
문제 4: 런타임 값
constexpr int square(int x) {
return x * x;
}
int main() {
int runtime_value;
std::cin >> runtime_value;
// ❌ constexpr 변수에 런타임 값
// constexpr int result = square(runtime_value); // 에러
// ✅ 일반 변수
int result = square(runtime_value); // OK (런타임 계산)
}
constexpr vs const
// const: 런타임 상수
const int x = getValue(); // 런타임 결정
// constexpr: 컴파일 타임 상수
constexpr int y = 42; // 컴파일 타임 결정
// constexpr 함수
constexpr int square(int x) {
return x * x;
}
// const 함수
int getValue() const {
return value;
}
constexpr과 최적화
// 컴파일 타임 계산
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
// 컴파일 타임에 계산됨 (런타임 비용 0)
constexpr int fact10 = factorial(10);
// 어셈블리:
// mov eax, 3628800 (직접 값 삽입)
}
FAQ
Q1: constexpr 함수는 언제 사용?
A:
- 컴파일 타임 계산
- 배열 크기, 템플릿 인자
- 성능 최적화
Q2: 런타임에도 사용 가능?
A: 네. 인자가 constexpr이 아니면 런타임 실행.
Q3: constexpr vs inline?
A:
- constexpr: 컴파일 타임 계산
- inline: 함수 인라인화
Q4: 모든 함수를 constexpr로?
A: 아니요. 가능한 경우만.
Q5: C++11 vs C++14 차이?
A: C++14는 일반 함수처럼 작성 가능.
Q6: constexpr 학습 리소스는?
A:
- “Effective Modern C++”
- cppreference.com
- “C++ Templates”
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ constexpr Lambda | “컴파일 타임 람다” 가이드
- C++ 컴파일 타임 프로그래밍 | “constexpr/consteval” 가이드
- C++ constexpr if | “컴파일 타임 분기” 가이드
관련 글
- C++ 컴파일 타임 프로그래밍 |
- C++20 consteval 완벽 가이드 | 컴파일 타임 전용 함수
- C++ constexpr if |
- C++ constexpr Lambda |
- C++ 컴파일 타임 최적화 | constexpr·PCH·모듈·ccache·Unity 빌드 [#15-3]