2009.06.27 18:20 책 정리/Modern C++ Design

내가 컴파일 타임 어써션(Compile-time assertions)을 처음 써 본것은 BOOST를 알고서 부터였다. 컴파일 타임에 정말 많은 것을 할 수 있다는 계기가 된 함수(?) 인데, 다음 코드를 컴파일 할 때 어떤 경고가 뜨는지 한번 보면, 짭짜른 맛이 느껴지면서, 자꾸 먹고 싶어 진다.

6번째 라인에서 컴파일이 되지 않는 것을 알 수 있는데, 이게 바로 BOOST_STATIC_ASSERT 이다. 쓸 수 있는 곳은 무궁무진하다. 예를 들어서, 캐스팅 함수를 만든다고 치자, 작은 타입에서 큰 타입으로 캐스팅 하는건 자연스럽고 잘 되지만, 큰 타입에서 작은 타입으로 캐스팅 하는건 아무래도 좀 위험하다는 것을 알 것이다.

하지만 이것을 프로그래머의 뇌 속에 각인 시키면서 코딩 하겠다는 것은란 관악산을 오르면서 물 한 모금 안마시고 오를 수 있다며 때쓰는 어린애와 다를 게 없다.

바로 이 때 시원한 물 한 모금이, BOOST_STATIC_ASSERT 이다. 자 보시라!

시원한 바람이 집안으로 들어와 졸린 눈의 열을 식혀 주는 것 같지 않은가? 아. 이야기가를 하다 보니까 BOOST 이야기였네, ㅋ 이번 테크닉에선  BOOST_STATIC_ASSERT 같은 컴파일 타임 어써션(Complie-time assertions)을 만드는 방법을 소개 할려고 했다.

알다시피 작은 비트에서 큰 비트로 가는건 문제가 없지만, 큰 비트에서 작은 비트로 가는건 문제가 있는 캐스팅이 될 수가 있다. 간단하게 sizeof(작은 비트 타입) <= sizeof(큰 비트 타입) 일 경우에만 컴파일 하는 것인데, 컴파일 되게 하는건 쉬운데, "컴파일 되지 않게 하는 방법"은 잘 떠오르지 않을 것이다.

곰곰히 생각해 보면, 내가 컴파일 하다가 컴파일이 안되었던 적은 int 포인터에 char 포인터를 넣을 때라든지, 배열의 길이를 0으로 잡는다든지, enum type 에 그냥 값을 넣는다 든지, 상수를 바꿀려고 한다든지 등등등 무척 이나 많다.

이것 중 가장 쓰기 편한건 배열을 이용하는 방법이다. 각각 해보면 알겠지만, 포인터 변환은 두개의 포인터가 필요하고,  전처리기에서 분기시켜서 "sizeof(작은 비트 타입) <= sizeof(큰 비트 타입)" 일 때만 활성화 시키기만 하면 되는 것이다!
그러면 다음 처럼 만들 수 있다.

 벌써 해본 사람은 알겠지만, 컴파일이 되지 않는건 잘 되는데, 양파 까는 메세지보며 보게 된다. MSVC 2008 에선 "error C2466: 상수 크기 0의 배열을 할당할 수 없습니다." 이런 소리나 해대고 있다. 곰곰히 생각해 보면, 캐스팅 때문에 컴파일이 되지 않는 다는 메세지는 항상, "int 형을 char 으로 캐스팅 할 수 없다" 라고 출력해 주었던 기억이 떠오른다. 만약 #define 가지고 장난 좀 친다면 int 와 char 에 원하는 글짜를 넣을 수 있지 않을까?

좀 그럴싸 한데? 좀 더 #define 가지고 장난을 쳐보자.

이렇게 장난을 쳤더니, "safe_static_cast::ERROR_No_static_cast'에서 'CompileTimeCheck<false>'(으)로 변환할 수 없습니다."  얼추 메세지를 넘길 수 있게 되었다. sizeof() 트릭은 어디 책에서 봤었는데, "컴파일 타임에 크기를 계산한다" 라는 특징이 있기 때문에, 함수의 리턴 타입이나, 임의의 타입의 객체라든지 컾마일 타임에 계산해 주는 연산자라고 배웠(?)고, void 트릭은 boost::checked_delete에서 보고 kldp 에 질문을 올려서  배웠다. 컴파일 타임에 문법만 검사하고 런타임에 제거된다고 한다.

void와 sizeof에 대해서 시간 날 때 정리 하도록 하자.(사실 나도 잘 모른다...)

sizeof 에 대해서 다시 정리하고 밑에것 올릴 것

여담
책에선 sizeof 을 잘못 사용 했다. sizeof( 피연산자 ) 형식으로 사용 되는데, 여기서 말하는 피연산자로는 "함수 타입"이 올 수 없다. 밑의 소수 중에 컴파일 에러 나는 부분의 sizeof(int()) 는 위에 있는 int() 와 다르게 type-id 로 간주되어, 함수 타입이 된다. 그러므로, 컴파일이 안된다고 한다.

자세한 것은 http://www.gpgstudy.com/forum/viewtopic.php?topic=23605 참고 하는게 좋을 듯 싶다.

 예외적으로 함수의 경우 리턴되는 타입의 크기가 고정적이기 때문에 함수만 정의(평가)가 끝났다고 인식된다.

저작자 표시
신고
posted by 농사를 짓는 게임 프로그래머 최익필

댓글을 달아 주세요