여기서는 템플릿 메타 프로그래밍(이하 TMP)와 constexpr
에 대해 알아보지 않습니다. constexpr
이 왜 등장했는지에 대한 제 의견과 constexpr
을 어떻게 사용해야 할 것인가에 대한 글입니다.
추가 1.
constexpr
에 대해 잘 정리한 글을 덧붙입니다.
템플릿 메타 프로그래밍(Template Meta Programming)
흑마법으로 분류되어 현재는 잘 안쓰이는 것으로 알려진 TMP로 무엇을 할 수 있는지 봅시다. TMP로 피보나치 수열을 구하는 방법입니다. (물론 좋은 예시는 아닙니다.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <int T>
struct Fibonacci { enum { Value = (Fibonacci<T - 1>::Value + Fibonacci<T - 2>::Value) }; };
template <>
struct Fibonacci<0> { enum { Value = 1 }; };
template <>
struct Fibonacci<1> { enum { Value = 1 }; };
template <>
struct Fibonacci<2> { enum { Value = 1 }; };
// **Example**
// Fibonacci<10>::Value;
// result: 55
위와 같이 피보나치 수열을 컴파일 타임에 구할 수 있습니다. 근데 더 복잡한 함수를 작성하는 경우 컴파일이 안되거나 디버깅이 어려워지기 시작합니다.
constexpr(Constant Expression)
위에서 작성한 피보나치 수열을 컴파일 타임에 구할 수 있으면서 TMP를 안쓰기 위해서 constexpr
을 사용할 수 있습니다. (이 또한 좋은 예시는 아닙니다.)
1
2
3
4
5
6
7
8
constexpr unsinged int getFibonacci(unsinged int input)
{
return (input <= 1u) ? input : getFibonacci(input - 1) + getFibonacci(input - 2);
}
// **Example**
// getFibonacci(10);
// result: 55
개인적인 견해로 TMP를 대체하기 위해 constexpr
이 나오지 않았나 합니다.
constexpr은 언제 써야하는가
- TMP는 거의 쓰지 않는다.
- 컴파일 타임 계산이 필요한 경우인지 고민해본다. (예: 해시 함수)
- 필요하다고 판단하는 경우
constexpr
을 붙인다.
- 주의: 재귀 함수가 너무 깊은 경우 컴파일러가 포기하고 일반 함수로 만들수도 있다. (TMP의 경우 컴파일 에러)