2009-09-29 7 views
3

C++에서 템플릿 클래스를 사용하는 경우라면 구현이 헤더 파일에 있거나 헤더 파일의 하단에 # 포함되어 있어야합니다.C++ templates : 헤더 파일이 여전히 손상 되었습니까?

저는 C++ 템플릿을 몇 년 동안 사용하지 않았습니다. 방금 다시 사용하기 시작한 후이 동작이 인 것처럼 보일 경우이 지속되는 것으로 나타났습니다. 아직도 그렇습니까? 또는 컴파일러가 구현을 인터페이스와 분리하여 충분히 스마트하게 만들었습니까?

+0

내보내기를 사용하더라도 소스를 공개하지 않아도됩니다 (어떤 형식이든). ".et 파일은 프런트 엔드에게 내 보낸 템플릿 정의의 위치 만 알려주고 실제로 정의를 포함하지는 않으므로 내 보낸 템플릿 정의가 포함 된 소스는 인스턴스화시 사용할 수 있어야합니다 (일반적으로 * 특히, 내보내기 기능은 소스 형식으로 템플릿 정의를 게시하지 않기위한 메커니즘이 아닙니다. "(강조 표시) –

+0

@litb : 자극적입니다. 그러나 당신의 대답에 감사드립니다. –

+0

나는 실제로 컴파일러를 구현하지 않았기 때문에 나는 그것을 말하는 위치에 있지 않다. 그러나 나는 EDG의 창조자를 믿는다. –

답변

2

선언과 구현을 구분하기 위해 표준에서는 사용자가 내보내기 키워드를 사용해야합니다. 내가 아는 한, 그것을 처리하는 방법을 알고있는 컴파일러는 오직 하나뿐입니다 .Comeau.

그러나 C++ 0x에는 특정 전문화를 자동으로 인스턴스화하지 않도록 컴파일러에 알리는 메커니즘 (extern templates)이 포함됩니다. 따라서 컴파일 시간을 줄이려면 특정 컴파일 단위에서 일부 전문을 명시 적으로 인스턴스화하고 헤더에서 extern으로 선언하여 컴파일 시간을 단축 할 수 있습니다.

2

(export 키워드 사용) 템플릿은 Comeau C++ (: C++ FAQ Lite)에 의해서만 지원되는 것으로 보이는 템플릿입니다.

구현 코드가없는 인터페이스를 유지하는 일반적인 기술은 인라인 함수 정의를 선언 헤더의 끝에 포함 할 수있는 별도의 "구현"헤더에 넣는 것입니다.

+0

솔직히 말하면, 나는 수출을 찾고있는 것이 아닙니다. 다른 언어 기능과 마찬가지로 템플릿 내부에 템플릿 구현을 포함하지 않아도되는 헤더를 찾고있었습니다. –

1

수출은 EDG 프론트 엔드에 의해서만 지원되며, 상업적으로는 내가 알고있는 한 Comeau 컴파일러에서만 사용할 수 있습니다.

내보내기는 컴파일러 작성자의 막대한 노력이 필요하지만 소스 공개가 필요 없으며 컴파일 종속성도 줄이지 않습니다.

그래서 Herb Sutter는 컴파일러 빌더에게 '내보내기를 잊어라'고 물었습니다. 필요한 시간 투자가 다른 곳에서 쓰는 것이 더 좋을 것이므로 ... 얼마나 오랜 시간이 걸리고 얼마를 얻은지를 본 후에 다른 컴파일러가 수출을 구현할 것이라고 생각하지 않습니다.

이 논문은 "왜 우리가 수출 할 여력이 없는가?"라고 말하면서 Sutters blog에 있지만 PDF는 없다. (빠른 구글이 그것을 만들어야한다.) 6 년 전, 나는 그들이 모두 듣고 방해 :

많은 사람들이 두 개의 헤더 파일 (예를 들어 .hpp.ipp) 만 선언 하나, 그리고 정의에 하나를 사용 그것은 단순히 다른 하나를 포함하는 문제입니다.

foo.hpp

#ifndef MY_TEMPLATES_HPP 
#define MY_TEMPLATES_HPP 

template< class T > 
void foo(T & t); 

#include "foo.ipp" 
#endif 

foo.ipp

#ifdef MY_TEMPLATES_IPP 
    nonsense here, that will generate compiler error 
#else 
#define MY_TEMPLATES_IPP 

template< class T > 
void foo(T & t) { 
    ... // long function 
} 

#endif 

이 단지 이익 물론 일부 선명도는 아무것도 정말 단순히 하나 개의 헤더 파일에 모든 인라인 비교되지 변경합니다.

+0

당신이 참조한 PDF 파일을 찾았습니다 : http://ra.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1426.pdf, 2003 년 3 월 일자 –

+0

@Matthieu M. : PDF가 깨졌습니다. 더 나은 원본 가져 오기 : http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1426.pdf – paercebal

+0

@paercebal : 감사합니다! –

3

기술적으로 그들은 이 아니며 헤더 파일에이 필요합니다.

이 사용 예는 고정 된 버전 세트가있는 템플릿 클래스가있는 경우입니다 (인수 sake char 및 wchar_t). 그런 다음 모든 메소드를 소스 파일에 넣고이 두 버전을 명시 적으로 인스턴스화 할 수 있습니다.이것은 다른 사람들이 사용할 의도가없는 유형의 템플릿을 조정할 수없는 안전성을 가지고 있습니다. (이 배포가 제공되지 않기 때문에)

// X.h 
template<typename T> 
class X 
{ 
    // DECLARATION ONLY OF STUFF 
    public: 
     X(T const& t); 
    private: 
     T m_t; 
}; 

// X.cpp 
#include "X.h" 

// DEFINTION OF STUFF 
template<typename T> 
X<T>::X(T const& t) 
    :m_t(t) 
{} 

// INSTANCIATE The versions you want. 
template class X<char>; 
template class X<wchar_t>; 


// Main.cpp 
#include "X.h" 

int main() 
{ 
    X<chat> x1('a'); 
    X<wchar_t> x2(L'A'); 
    // X<int>  x3(5); // Uncomment for a linker failure. 
} 

가정 사람들은 직접 X.cpp을 포함 할 수 없습니다 다음 다른 X < INT> 또는 X < 플로트> 등 그러나 abovr 클래스가 완전히 있습니다을 사용할 수 없습니다 한정된.

나는 또한이 기술을 사용하여 컴파일 시간을 줄이는 것을 보았다. 각 컴파일 단위가 동일한 버전의 X를 다시 생성하지 않기 때문에 한 곳에서 정의 만 얻을 수 있습니다 (따라서 하나의 컴파일 비용). 이 크기로 축소하면 사용하는 각 X 버전의 X를 수동으로 설치해야합니다.

+0

이것은 내가 필요한 것을하지는 않지만 꽤 개성이있다. 나는 그것을 기억할 것이다. –

0

GCC는 모든 템플릿을 명시 적으로 인스턴스화하지 않는 한 긴 수집 단계를 거칩니다. VC++는 대처하고있는 것처럼 보입니다.하지만 어쨌든이 단계를 피하는 것이 더 좋습니다. 템플릿을 어떻게 사용할 것인지를 알고 싶습니다. 일반적으로 응용 프로그램의 경우가 아니라 라이브러리의 경우가 많기 때문에 템플릿 정의를 별도의 파일에 저장합니다. 또한 선언을 구현 세부 사항에 덜 복잡하게 만들어 코드를보다 쉽게 ​​읽을 수 있습니다.

관련 문제