const, constexpr은 상수를 나타내는 키워드입니다. C++98 이하 버전까지는 constexpr이 없었는데요, C++11부터 constexpr specifier가 도입됐습니다. 

const int a = 1;
constexpr int b = 2;

a = 3;	// compile error
b = 4;	// compile error

 

 

const, constexpr 둘 다 똑같은 것 같은데, 무슨 차이가 있을까요?

많은 차이점이 있지만, 가장 큰 차이점은 const는 런타임 상수(runtime constant)이고, constexpr은 컴파일 시간 상수식(compile-time constant expression)입니다.

constexpr(=const expression)은 변수나 함수의 반환값이 컴파일 타임에 상수식(constant expression)으로 표현될 수 있어야 합니다.

 

int input;
cin >> input;

const int BITS = input;
auto bin = bitset<BITS>(1); // compile error
auto arr[BITS];             // compile error

런타임 상수와 컴파일 시간 상수식은 거의 동일하지만, C++에서 컴파일 타임 상수식만 요구하는 경우가 몇 가지 있습니다.

  • 배열 선언시 size
  • bitset 선언시 size
  • 등등

 

#include <bits/stdc++.h>

using namespace std;

// C++11 constexpr functions use recursion rather than iteration
// (C++14 constexpr functions may use local variables and loops)
constexpr int factorial(int n)
{
	return n <= 1 ? 1 : (n * factorial(n - 1));
}

constexpr int factorial2(int n)
{
	return n <= 1 ? 1 : (n * factorial2(n));	// 무한루프
}

int main()
{
	int arr1[factorial(3)];  // ok
	int arr2[factorial2(3)]; // compile error (C2131)

	return 0;
}

constexpr 키워드는 함수 앞에도 쓸 수 있습니다. 이때, C++11의 경우 지역변수나 반복문을 사용하지 못하고, return 뒤에 모든 식을 넣어야 하며, 반복문을 사용하려면 재귀형식으로 사용해야 합니다.

C++14에서는 지역변수, 반복문 사용 가능하고 return에 모든 표현식을 다 넣을 필요가 없어졌습니다.

 

만약 식이 상수로 계산되지 않는다면 (depth 초과, step 초과 등) 컴파일 에러가 발생합니다.

예를 들면 msvc의 constexpr depth 제한은 512이고, steps 제한은 100000 이라고 하네요.

 

컴파일러마다 컴파일 옵션을 통해 constexpr의 depth 제한이나 step 제한 등을 조절할 수도 있습니다만 컴파일 에러가 나면 보통은 무한루프에 빠진 것이니 식을 점검해보는게 낫습니다.

반응형