Tech & IT/프로그래밍

C++ template에서 export keyword(VS2008에서는 아직 미지원)

해피콧 2008. 11. 28. 15:43
'); }
'); }

오늘은 export라는 키워드를 간단하게 소개하겠습니다. 

질문답변란에 올라온 질문에 대해서 찾다 보니 알게 된 내용입니다.

Template을 사용할 때는 함수의 구현 부분이 그 함수 앞에 있어야 합니다. 따라서 보통은 헤더 파일에 들어가게 되지요. [The C++ Programming Language] 책을 보니 export라는 키워드가 있는데 Visual C++에서는 지원을 하지 않습니다. export를 사용하면 컴파일러가 컴파일을 할 때 그 함수가 정의된 곳을 찾아서 알아서 잘 컴파일해야 한다고 합니다. (이거... 구현하기 귀찮겠네요. -_-;)

다음과 같이 사용하면 된다고 하니 참고하세요.

[out.h]

template< class T>  void out(const &T t);

[out.cpp]

#include < iostream> 
#include "out.h"

export template< class T>  void out(const &T t)
{ 
    std::cerr < <  t;
}

[user1.cpp]

#include "out.h"

// out() 함수를 잘 사용한다.

[user2.cpp]

#include "out.h"

// out() 함수를 잘 사용한다.


ps. 제가 자료실에 올린 "C++의 변경점"이라는 글을 보시면 export에 대한 좀 더 자세한 설명이 나옵니다. 그러나... 굳이 받아보실 분이 없을 것 같으니... 그 부분을 그냥 붙입니다.

export : 분할 Compilation과 template

C++ template 방식의 가장 커다란 문제점 중의 하나는 바로 separate compilation을 지원하지 않는 다는 점이었다. 물론 그 동안 C++ 컴파일러마다 각자 고유의 방식으로 언어를 확장하거나 또는 별도의 기법을 사용하여 이와 같은 문제점을 해결해 왔다. 그러나 표준화가 이루어지지 않은 확장은 template을 빈번히 사용하는 소프트웨어의 이식성 및 상품화에 커다란 제약이 아닐 수 없었다. 지금까지도 대부분의 template 코드는 inline 함수가 처리되는 방식과 거의 동일한 방식으로 제작되고 사용되어왔다. 그러므로 일반적으로 template 코드는 헤더 파일 내에 완전한 코드를 제공해야 하며 선언과 정의를 분할하지 않는 것이 통상적인 관례였다. 그러나 다음처럼 각기 다른 linkage 방식이 적합한 경우가 함께 공존하는 경우는 커다란 문제 거리가 아닐 수 없다.

// Thing.h
template< class T>
struct Thing {
    void veryShortCode();
    void veryLongCode();
};
template< class T>
inline
void Thing< T>::veryShortCode() {}
template< class T>
inline
void veryLongCode() { // really really long long 
code .... 
   whether you believe or not
} 

위와 같은 경우 Thing::veryLongCode()는 외부 파일에 정의되어 있고 컴파일러가 필요한 코드만 생성해서 분할 컴파일할 수 있다면 문제는 해결되는 것이다. 다소 늦은 감이 있으나 이제라도 그러한 기능이 추가되고 표준화되었으니 다행한 일이 아닐 수 없다. 표준 문서에 정의된 기능을 지원하는 컴파일러는 아직 본적이 없지만 새로이 추가된 export keyword가 이와 같은 역할을 하는 것으로 만일 분할 컴파일이 필요한 경우가 있다면 선언 또는 정의 시에 export라고 간단히 명시하기만 하면 된다(컴파일러 만드는 사람들은 간단하지 않겠지만) .

// Thing.h
...
template < class T> void veryLongCode(); 
// 또는 export template<  ....
// Thing.cpp
template< class T >
export veryLongCode { ... }  // 

이제 Thing class의 사용자는 단지 Thing.h만을 포함하면 되고 실제로 export된 veryLongCode의 정의를 읽어 필요한 code를 생성하여 후에 연결하는 작업은 컴파일러가 할일이다. 또한, 각각의 member를 일일이 export 또는 inline하는 것은 매우 불편한 작업이다. 때문에 이러한 경우 일단은 전체 class를 export하면 편리하다.

// Thing.h
export
template< class T>
struct Thing {
    void veryShortCode();
    void veryLongCode();
};

그러나 특정 member만이 inline되어야 할 경우에는 class 정의 밖에서 명시적으로 inline keyword를 붙여주거나 아예 class 내에서 code를 정의하면 된다. 이때 inline의 효과는 export를 무마하기 때문에 지정된 code만은 inline 방식으로 사용될 수 있다.