일단 변수가 컴파일 타임이다 아니다라는 표현이 좀 이상함
이게 기계어로 변환되었을때 무조건 literal로만 표현되어야 한다는 얘기라면 이건 C++ 표준이랑 상관 없음
그게 아니라 초기화 얘기라면
A constexpr variable must satisfy the following requirements:
...
- the full-expression of its initialization, including all implicit conversions, constructors calls, etc, must be a constant expression
이 말이 초기화 expression이 컴파일 타임이어야 한다는 얘기임
실제로
constexpr int f( int n ) { return n + 1; }
요런 constexpr 함수가 있을때
constexpr int n = f( 1 ); <- 컴파일 됨
int* _n = new int{};
constexpr int n = f( *_n ); <- 컴파일 안됨
그리고 이런 것도 되야됨
if constexpr ( n > 0 );
SomeStructTemplate< n >{};
정리하면 constexpr variable은
1. 초기화: 컴파일 타임 (constexpr 함수가 초기화 expression에 쓰이면 컴파일 타임 계산을 보장함 아니면 컴파일 안됨)
2. 컴파일 타임 evaluation을 요구하는 곳에 쓸수 있음 (if constexpr, template)
3. (기계어로 컴파일됐을때) 피연산자로 쓰일때 주소값을 갖을수는 있음 <- c++ 표준이 관여할 사안이 아님
해당 댓글은 삭제되었습니다.
컴파일 타임에 evalution이 안되는 expression이면 컴파일 에러남
당연히 런타임이냐 컴파일타임이냐 얘기지 갑자기 무슨 시점 얘기야 그리고 애초에 컴파일 타임의 evaluation은 하든 안하든 그 자체로는 최종 어셈코드상 아무 차이가 없다 아무 의미도 없고 실제로 eval을 했는지 안했는지조차 알수가 없다는 얘기임 그리고 초기화시 side effect 가 없고 이후 쓰이지도 않는 변수를 날리는건 일반 변수도 마찬가지다 마지막으로 constexpr 변수는 컴파일 타임 evaluation이 "가능"하다는 보장이 아님 그게 requirement라고
side-effect가 없는 변수를 없애는건 constexpr가 아니어도 가능한거다
먼저 constexpr가 컴파일 타임에 evaluation 가능한지 확인 (C++ 요구조건), 불가능하면 "컴파일 에러" 그 다음에 해당 변수가 side-effect를 가져오는지 확인, 없으면 컴파일러 알아서 최적화 constexpr가 컴파일 타임에 evaluation이 최소 한번은 되야지 side-effect가 있는지 없는지 알지
윗댓 나한테 하는 얘긴지 모르겠는데 side effect 없는 일반 변수 역시 컴파일러가 없앤다는 얘기는 나도 한 얘기고 님 얘기 틀린게 side effect가 있으면 애초에 컴파일 타임 evaluation이 불가능하다는 얘기임 constexpr 변수 requirement에 부합되지 않으므로 컴파일 에러임. 에러 안나면 컴파일러 버그 혹은 ill-formed, NDR이고 이런 케이스에도 ill-formed NDR이 있는지는 모르겠다만
아 윗댓 다시 읽어보니 사이드 이펙트 얘기가 변수가 이후에 쓰이는지에 대한 얘기였구나 변수 초기화 expression에서의 사이드 이펙트를 얘기하는줄 ; 죄송
컴파일 타임에 evaluation이 되야한다는거야 다 아는 사실이고 실제로 컴파일 타임에 그거 구하고 말고는 컴파일러 마음이라는 소리 아님?
아 좀 이상하게 썼노.. 컴파일 타임에 무조건 evaluation 가능한건 맞는데 실제로 컴파일러가 무조건 그렇게 한다는 보장은 없다고
그럼 constexpr int n 저거를 나중에 템플릿 인자로 넣으면 어떻게 할건데 이건 런타임에 계산할건데 후훗 그러다 앗 ㅅㅂ 템플릿이네 그러고 다시 올라가서 컴파일 다시함?
물론 컴파일러가 그런 ㅄ짓을 안하리란 보장은 없지만 일부러 할 이유도 없지 이거 말고도 c++ 에 그런게 몇개 있어
예를 들면 class 생성자 바디 안에 들어오면 버츄얼 테이블이 완성되어 있다든지 c++ 표준 어디에도 그런 언급은 없지만 다른 요구조건들을 해결하려면 컴파일러가 버츄얼 테이블을 그 전에 만들수밖에 없거든 사용자 입장에선 저 정도면 그냥 암시적으로 보장되어있다 생각하고 쓰는거지
지식이 늘었다
아 그리고 constexpr 함수도 컴파일러가 무슨 지 맘대로 런타임에 계산할지 컴파일타임에 할지 정하는게 아님 표준에는 적어도 하나 이상의 컴파일 타임 eval을 보장하는 패쓰가 있어야 된다고 되어 있음 이 패쓰로 가는 argument를 넣으면 표준을 준수하는 컴파일러들은 다 컴파일 타임에 계산을 해야 될거다 근데 이건 100% 확신은 없네 표준 워딩이 워낙 애매해서 근데 이것도 템플릿 인자로 바로 넣을수 있기 때문에 별다른 수는 없을거라 봄