문제

나는 거의 전적으로 구성된 도서관을 사용하고 있습니다. 헤더 파일의 템플릿 클래스 및 기능, 이와 같이:

// foo.h
template<class T>
class Foo {
  Foo(){}
  void computeXYZ() { /* heavy code */ }
};
template<class T>
void processFoo(const Foo<T>& foo) { /* more heavy code */ }

이제 이것은 나쁘기 때문입니다 컴파일 시간은 견딜 수 없습니다 해당 헤더 파일 중 하나를 포함 할 때마다 (실제로 각 컴파일 장치에 많은 것을 포함).

템플릿 매개 변수로서 각 라이브러리 헤더 파일에 대해 하나 또는 두 가지 유형 만 사용합니다. 선언 만 포함하는 파일, 중공 코드가 없으면 다음과 같은 것입니다.

// NEW: fwd-foo.h
template<class T>
class Foo {
  Foo();
  void computeXYZ();
};
template<class T>
void processFoo(const Foo<T>& foo);

그런 다음 필요한 모든 인스턴스를 생성하는 하나의 파일. 그 파일이 될 수 있습니다 한 번에 별도로 편집되었습니다:

// NEW: foo.cpp
#include "foo.h"
template class Foo<int>;
template class Foo<double>;
template void processFoo(const Foo<int>& foo);
template void processFoo(const Foo<double>& foo);

이제 나는 그냥 포함 할 수 있습니다 fwd-foo.h 내 코드에서 짧은 컴파일 시간이 있습니다. 나는 반대 할 것이다 foo.o 결국.

물론 단점은이 새로운 것을 만들어야한다는 것입니다. fwd-foo.h 그리고 foo.cpp 스스로 파일. 물론 유지 보수 문제입니다. 새 라이브러리 버전이 출시되면 해당 새 버전에 적응해야합니다. 다른 단점이 있습니까?

그리고 나의 주요 질문은 다음과 같습니다.

이 새 파일을 만들 수있는 기회가 있습니까? fwd-foo.h, 자동으로 원본에서 foo.h? 많은 라이브러리 헤더 파일 (아마도 20 정도)에 대해이 작업을 수행해야하며 특히 새 라이브러리 버전이 출시되고 새 버전으로 다시 수행 해야하는 경우 자동 솔루션이 가장 좋습니다. 이 작업에 사용할 수있는 도구가 있습니까?

편집하다:

추가 질문 : 새로 지원할 수있는 방법 extern 키워드이 경우에 도움이 되나요?

도움이 되었습니까?

해결책

우리는 사용 lzz 단일 파일을 별도의 헤더 및 번역 장치로 나눕니다. 기본적으로 일반적으로 템플릿 정의를 헤더에도 넣지 만이를 원하지 않도록 지정할 수 있습니다.

사용할 수있는 방법을 보여주기 위해 다음을 고려하십시오.

// t.cc
#include "b.h"
#include "c.h"

template <typename T> 
class A {
  void foo () {
    C c;
    c.foo ();
    b.foo ();
  }
  B b;
}

위 파일을 가져 와서 't.lzz'파일로 복사하십시오. 배치하십시오 #포함 필요에 따라 별도의 $ HDR 및 $ SRC 블록으로 지시 :

// t.lzz
$hdr
#include "b.h"
$end

$src
#include "c.h"
$end

template <typename T> 
class A {
  void foo () {
    C c;
    c.foo ();
    b.foo ();
  }
  B b;
}

이제 마지막으로 템플릿 정의를 소스 파일에 배치하도록 지정하는 파일에서 lzz를 실행하십시오. a를 사용 하여이 작업을 수행 할 수 있습니다 $ Pragma 소스 파일에서 또는 명령 줄 옵션 "-ts"를 사용할 수 있습니다.

이로 인해 다음 파일이 생성됩니다.

// t.h
//

#ifndef LZZ_t_h
#define LZZ_t_h
#include "b.h"
#undef LZZ_INLINE
#ifdef LZZ_ENABLE_INLINE
#define LZZ_INLINE inline
#else
#define LZZ_INLINE       
#endif
template <typename T>
class A
{
  void foo ();
  B b;
};
#undef LZZ_INLINE
#endif

그리고:

// t.cpp
//

#include "t.h"
#include "c.h"
#define LZZ_INLINE inline
template <typename T>
void A <T>::foo ()
          {
    C c;
    c.foo ();
    b.foo ();
  }
#undef LZZ_INLINE

그런 다음 일부 Grep/SED 명령을 통해 실행하여 LZZ Helper 매크로를 제거 할 수 있습니다.

다른 팁

사전 컴파일 된 헤더를 사용해보십시오. GCC와 MSVC 가이 기능을 지원한다는 것을 알고 있습니다. 그러나 사용량은 벤더에 따라 다릅니다.

나는 꽤 오랫동안 같은 문제를 해결하고 있습니다. 제안하는 솔루션에서는 템플릿 클래스를 두 번 정의하는 것입니다. 동일한 순서 (동일한 순서로)를 정의하면 괜찮지 만 조만간 문제가 발생할 수 있습니다.

내가 생각해 낸 것은 다른 방법으로 문제를 고려하는 것입니다. 구현을 전문으로하지 않는 한 우아하게 작동합니다.

AVOIS는 구현 파일에서 템플릿 인수를 업데이트 해야하는 두 개의 매크로를 사용합니다 (기본 템플릿 인수를 클래스에 추가하려면 조심하십시오).

// foo.h
#define FOO_TEMPLATE template<typename T>
#define FOO_CLASS Foo<T>

FOO_TEMPLATE
class Foo {
  Foo();
  void computeXYZ();
};

// foo_impl.h
#include "foo.h"
FOO_TEMPLATE
FOO_CLASS::Foo(){}

FOO_TEMPLATE
void FOO_CLASS::computeXYZ() { /* heavy code */ }

이렇게하면 본질적으로 비 테일 플레이트 클래스와 동일한 방식으로 작업합니다 (물론 템플릿 함수로 동일한 작업을 수행 할 수 있습니다).

편집 : C ++ 0X의 외부 키워드 정보

C ++ 0X의 외부 키워드가 도움이 될 것이라고 생각하지만 모든 것을 마술처럼 해결하지는 않습니다!

에서 이 기사,

외부 템플릿

템플릿을 인스턴스화하는 모든 모듈은 본질적으로 객체 코드에서 사본을 생성합니다. 그런 다음 마지막 단계에서 모든 중복 객체 코드를 폐기하는 것은 링커에 달려있어 프로그래머의 날 (또는 때로는 공상)을 구성하는 임계 편집 컴파일 링크주기가 느려집니다. 이 객체 코드 쓰레기 수집을 단락시키기 위해 많은 컴파일러 공급 업체가 이미 템플릿 앞에서 갈 수있는 외부 키워드를 구현했습니다. 이것은 기존 산업 관행을 체계화하는 표준화의 경우입니다 (PUN 의도). 실제로, 이것은 기본적으로 "여기에 인스턴스화하지 않는다"는 통지를 기본적으로 통지를 보내서 구현됩니다.

extern template class std::vector;

C ++ 0X는 외부 템플릿으로 컴파일 시간 문제를 해결합니다. 그래도 당신이 요구하는 일을하는 자동적인 방법을 모르겠습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top