Introduction

1부에선 "주문형 인스턴스화"를 통해, 언제 인스턴스화가 필요한지 알게 되었다면, 게이른 인스턴화 부분에선 좀 더 세부적으로 인스턴스화 되는 시기를 정리한다. 여기서 말하는 세부적이란, 기존에선 인스턴스화 자체에 대해서 이야기 했다면, 이 부분은 템플릿 코드의 내부 요소, 즉 클래스 템플릿의 멤버들이 언제 인스턴스화 되는지 정리 되었다는 것을 의미한다.

Content

게으른 인스턴스화

코드를 보고 규칙을 파악하는게 더 빠르므로, 예제코드(책에서 발취)를 첨부하고 하나씩 정리해 보겠다.


우선 책의 내용과 주로 쓰는 MSVC의 경우 상이하게 틀리기 때문에, 책을 내용을 기준으로 설명하고 MSVC의 내용을 추가 설명하는 형태로 정리를 해 나가겠다.

일반적으로 C++ 컴파일러는 문법이나 의미상의 제약 조건을 검사하기 위해 템플릿 정의를 우선 컴파일 한다. 이때 템플릿 파라미터는 유효한것이 기입되었다는 가정하에서 진행 된다. 즉, Danger 클래스 템플릿에 쓰이는 템플릿 파라미터 N은 1 이상이 올 것이라고 가정한다는 말이다.  그러면 이제부터 Tricky 클래스 템플릿이 어떻게 검사 되는지 알아 보자.

1. 인스턴스화 전, 문법 검사를 할 경우

2지점에서 함수 인자인 Safe<T>는 정수 3으로 초기화 되지 않으나, 인자명이 없기 때문에, 표준 C++ 컴파일러는 문법검사시 "기본 인자가 필요 없겠네" 라고 판단하고 그냥 넘어간다고 한다. MSVC에서도 동일한지는 모르겠으나, 어찌되었던 MSVC도 패스 한다.

4지점에선 표준 컴파일러가 Tricky 클래스 템플릿이 인스턴스 전에 Danger<0>을 문법검사 할 때 오류를 벹어 낼 것 이라고 한다. MSVC에선 0이라 할지라도 문법 검사시 아무 에러가 없고,  Tricky의 객체를 생성해서 error() 함수를 호출을 해도 문제가 되지 않는다. 음수일 경우에만 컴파일 시 오류를 벹어 내는 점이 표준과 MSVC이 매우 다른 점이다.

5지점에선 void unsafe( T (*p)[N] ) 중 N이 음수이거나 0일 경우에도 표준 컴파일러는 문법검사 시 패스 한다고 나와 있으나, MSVC에선 0일 경우 패스하고 -1일 경우 컴파일 에러를 벹어 낸다.

2. 인스턴스화 후, 문법 검사를 할 경우

즉, main() 내부에 10 지점을 통해서 인스턴스화 한 후에 어떻게 문법 검사가 이루어 지는지를 설명한 것이다.

1지점에서 처럼 클래스의 객체가 생성 될 때, 생성자와 소멸자가 있어야 하듯이, 어딘가에 그 정의가 반드시 있어야 한다. 예제에선 소멸자만 있어도 컴파일이 되는 이유는 생성자나 소멸자 자체가 클래스에 정의되어 있지 않을 경우, 알아서 만들어 주기 때문이다. 가상함수가 virtual 이라는 점은 7지점 설명할 때 하겠다. MSVC에서도 마찬가지

2지점에서 Safe<T> = 3은 인스턴스화 되어도 컴파일이 될지 안될지는 책에서 언급을 하지 않았다.(단지 인스턴스화 전 문법 검사에서 걸리지 않는다고만 나와 있다.) MSVC에서 테스트 해보니 컴파일 에러가 발생 된다.

3지점은 실제로 클래스 템플릿이 인스턴스화 된다고 하여도, 사용하지 않았으므로, 컴파일 에러를 발생시키지 않는다.(MSVC도 마찬가지)

5지점은 예제에서 사용되지 않아 인스턴스화 되지 않지만, 인스턴스화 한다면, N이 0으로 평가 되기 때문에 컴파일 오류를 벹어낸다. 하지만 MSVC에선 음수가 아닌 이상 정상 컴파일 된다.

6지점은 operator->에서 T를 반환하기 때문에 연산자->를 사용하지 못하므로 문제가 되지 않겠나 생각해 볼수 있으나, C++에선 보다 유용하게 쓰이기 위해서 이 부분은 원하는 형태로 사용 할 수 있다고 한다. 대표적인 예로 std::auto_ptr<T> 나 boost::smart_ptr 들이 있다.

7지점에서 가상함수의 정의가 없는데, 이는 컴파일 에러를 불러 일으킨다. 가상 함수의 경우 반드시 정의가 있어야 하기 때문이다. 이는 가상 함수 호출 메커니즘에서 실체에 대한 주소가 필요하므로, 그 정의를 요구하기 때문이다. 소멸자가 가상이라면, 반드시 그 정의가 있어야 한다.(예제에선 명시되어 있다.), 아참 MSVC도 마찬가지로 에러를 벹어 낸다.

8지점은 실제로 클래스 템플릿이 인스턴스화 된다고 하여도, 사용하지 않았으므로, 컴파일 에러를 발생시키지 않는다.(MSVC도 마찬가지)

9지점은 예제코드가 잘못되어서, 아직 말할 시간이 안되었다. 에이콘 출판사에 문의한 상태이다.

Digression

보고 있는 책이 C++ Template 번역판이기 때문에, 책을 읽고 소화환 위의 정리에는 다소 많은 내용이 빠저 있다. 설명하는 방법도 많이 차이를 보이기도 한다. 그러므로 비싸지만 한권 사면 좋을것 같다. 144페이지의 예제가 잘못 되었다고 생각해서 현재 에이콘 출판사에 문의한 상태이다.

주제는 게이른 인스턴스화 인데, 정작 게이르게 인스턴스화 된다는 말이 없었다. 게이르다기 보다는 "영리한 인스턴스화" 라고 말하는게 더 좋다고 나는 생각한다.

템플릿 인스턴스화가 이루어지는 흐름을 보면, 해당 템플릿이 쓰이던 쓰이지 않던 1. 문법 검사를 무조건 하고, 2. 쓰이는 것들만(명시적이지 않아도 virtual 함수의 경우 묵시적으로 쓰인다) 인스턴스화 하고 3. 쓰이지 않는 것들은 인스턴스화 자체를 하지 않는다.


  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기