constexpr
Modern C++에 적응하기
Effective Modern C++ Chapter 3. constexpr
constexpr
constexpr
은 해당 값이 const
일 뿐만 아니라, 컴파일 타임 에 평가될 수 있음을 의미한다.
constexpr
로 선언된 객체는 const
이며, 그 값은 컴파일 타임에 정해진다. 따라서 컴파일 타임 이후에 평가되는 값으로 초기화할 수 없다.
1 | int sz; |
컴파일 타임에 정해진 상수이므로 배열의 길이나 템플릿 인수 등, 정수 상수 표현식 에 사용할 수 있다.
constexpr
로 선언된 함수는 함수에 넘겨지는 인수에따라 실행시점이 나뉜다.
- 인수가 컴파일 타임에 평가될 수 있다면, 함수의 결과 또한 컴파일 타임 상수로써 평가된다.
- 인수중 하나라도 컴파일 타임에 평가될 수 없다면, 보통의 함수처럼 런타임에 평가된다.
1 | constexpr int pow(int base, int exp) noexcept |
만약 constexpr
함수의 구현이 절대 컴파일 타임에 평가될 수 없다면 컴파일 에러가 발생한다.
1 | constexpr int pow(int base, int exp) noexcept |
std::pow
는 constexpr
로 선언된 함수가 아니다.(즉, 런타임에 평가된다.) 따라서 위 함수는 절대 컴파일타임에 평가될 수 없고, 컴파일 에러가 발생한다.
C++11 에서는 constexpr
함수를 정의할 때 지역변수를 사용할 수 없고, 하나의 반환 표현식만 사용해야 했다.[1]
1 | constexpr int pow(int base, int exp) noexcept |
C++14 부터는 이런 제약이 사라져 보다 자유로운 구현이 가능하다.
1 | constexpr int pow(int base, int exp) noexcept |
constexpr
의 반환 타입은 Literal Type 이어야 한다. 이는 컴파일 타임에 그 값을 알 수 있는 타입인데, C++11 에서는 void
를 제외한 기본 내장 타입이 여기에 해당한다.
생성자가 constexpr
이고, 멤버 변수도 컴파일 타임에 평가가 가능한 사용자 정의 타입 역시 리터럴에 속한다.
1 | class Point { |
C++14 부터는 void
가 Literal Type 에 포함되었고, C++11에서의 constexpr
함수는 암묵적으로 const
라는 제약이 사자렸기 때문에 setter 함수역시 constexpr
로 선언 가능하다.
1 | class Point { |
References
‘반환’ 표현식인 이유는
constexpr
함수의 반환 타입은 Literal Type 이어야한다는 제약 때문이다. C++11에서void
는 Literal Type이 아니었고, C++14부터 포함되었다. ↩︎