constexpr int size = 10;
constexpr은 기존의 const 보다 훨씬 더 상수성에 충실하며 충분히 깊게 이해할만한 가치가 있는 녀석이니 확실히 이해하고 활용할 수 있는 것이 중요하다.
C++11부터 지원되는 한정자 'constexpr'는 일반화된 상수 표현식(Generalized constant expression)을 사용할 수 있게 해주며, 일반화된 상수 표현식을 통해 변수나 함수, 생성자 함수 등에 대하여 컴파일 타임에서 상수인지 평가할 수 있도록 처리해준다. (C++17 부터는 람다 함수에도 constexpr 키워드 사용이 가능하다)
if constexpr(boolen)
// ~~~ statement-true
else
// ~~~ statement-false
if constexpr은 컴파일 타임에서 상수표현식의 boolean(true/false)를 평가한다.
따라서 인자로 무조건 bool 타입의 상수값이 와야 한다.
결과가 true일 경우엔 statement-false가 버려지며, false일 경우엔 statement-true가 버려진다. 버려진 코드는 컴파일 대상에서 아예 제외가 된다.
즉, 전처리기와 같은 컴파일 타임에서 코드가 제거되는 #ifdef와 같은 개념으로도 사용할 수 있다.
일단 const 로 정의된 상수들은 굳이 컴파일 타임에 그 값을 알 필요가 없다.
int a;
const int b = a;
하지만 constexpr 상수의 경우 뭐가 됬든 오른쪽에 무조건 상수식이 와야 한다.
int a = ;
'
'
'
constexpr int b = a; // compile error!
위 코드가 에러가 난 이유는 컴파일 후 런타임 도중에 a가 다른 값으로 바뀌었을지도 모르기 때문이다!
상수 b는 a의 최초 값(=상수성 값)을 알고 싶어하지만 a가 도중에 이리저리 치이면서
b에 대입할 때쯤엔 초기값 외의 값을 가질 수도 있기 때문이다.
const int c = 10;
constexpr int b = c; // ok
그래서 constexpr 상수는 처음부터 상수성을 확실하게 갖춘 녀석만 대입할 수 있다.
상수 c는 컴파일 타임(최초)부터 10인게 확실하니 값을 대입할 수 있게 된다.
사실 아래와 같은 상수는 언제 초기화될 지 알 수 없다.
const int i = x;
x가 변하지 않는 부동값일 경우 컴파일러가 컴파일 타임에서 바로 x 값으로 초기화 할거고
x가 중간에 다른 값으로 변할 경우 컴파일러는 i를 직접 i가 위치한 코드가 실행될 때인
즉 런타임 중에서 상수를 x 값으로 초기화한다. (최신 x값을 알아야 하기에)
이러한 모순적인 관계를 해결하고 최초의 원시 값(immutable value)을 사용하고 싶다면
컴파일 타임에서 확실히 상수를 사용할 수 있는 constexpr 키워드를 사용해야 한다.