스택큐힙리스트

외부 템플릿 (C++11)을 사용하여 인스턴스화를 피합니다. 본문

카테고리 없음

외부 템플릿 (C++11)을 사용하여 인스턴스화를 피합니다.

스택큐힙리스트 2023. 11. 18. 00:19
반응형

그림 1: 함수 템플릿


TemplHeader.h


template<typename T>
void f();

TemplCpp.cpp


template<typename T>
void f(){
//...
}
//명시적 인스턴스화
template void f<T>();

Main.cpp


#include TemplHeader.h
extern template void f<T>(); //이것이 올바른 방법인가요?
int main() {
f<char>();
return 0;
}

extern template를 사용하는 올바른 방법인가요, 아니면 그림 2와 같이 클래스 템플릿에만 이 키워드를 사용해야 하나요?


그림 2: 클래스 템플릿


TemplHeader.h


template<typename T>
class foo {
T f();
};

TemplCpp.cpp


template<typename T>
void foo<T>::f() {
//...
}
//명시적 인스턴스화
template class foo<int>;

Main.cpp


#include TemplHeader.h
extern template class foo<int>();
int main() {
foo<int> test;
return 0;
}

저는 이 모든 것을 한 개의 헤더 파일에 넣는 것이 좋다는 것을 알고 있지만, 같은 매개 변수로 템플릿을 여러 파일에서 인스턴스화한 경우, 여러 개의 같은 정의가 생성되어 오류를 피하기 위해 컴파일러가 이들을 모두 제거할 것입니다 (한 개만 남김). extern template를 어떻게 사용해야 할까요? 이는 클래스에만 사용할 수 있는지, 함수에도 사용할 수 있는지 궁금합니다.


또한, 그림 1과 그림 2는 템플릿이 한 개의 헤더 파일에 있는 솔루션으로 확장될 수 있습니다. 이 경우, 다중 동일한 인스턴스화를 피하기 위해 extern template 키워드를 사용해야 합니다. 이는 클래스에만 해당되는 것인지, 함수에도 해당되는 것인지 궁금합니다.

답변 1

만약 두 개의 파일이 함께 링크되는 경우, void ReallyBigFunction<int>()은 버려질 것이고, 컴파일 시간과 객체 파일 크기가 낭비될 것입니다.


컴파일 시간과 객체 파일 크기를 낭비하지 않으려면, extern 키워드를 사용하면 템플릿 함수를 컴파일하지 않도록 할 수 있습니다. 이 기능은 해당 이진 파일에서 사용되는 것을 알고 있을 때에만 사용해야 합니다.


source2.cpp를 다음과 같이 변경하면:


// source2.cpp
#include header.h
extern template void ReallyBigFunction<int>();
void something2()
{
ReallyBigFunction<int>();
}

다음과 같은 객체 파일이 생성됩니다:


source1.o
void something1()
void ReallyBigFunction<int>() // 한 번만 컴파일됨
source2.o
void something2()
// extern 때문에 ReallyBigFunction<int>이 없음

두 개의 파일이 연결되면 두 번째 object 파일은 첫 번째 object 파일에서 심볼을 사용합니다. 폐기하거나 컴파일 시간과 object 파일 크기를 낭비할 필요가 없습니다.


이는 프로젝트 내에서만 사용해야 합니다. 예를 들어 여러 번 vector<int> 템플릿을 사용하는 경우 한 개의 소스 파일을 제외하고 모두 extern을 사용해야 합니다.


이것은 클래스, 함수 및 템플릿 멤버 함수에도 적용됩니다.

답변 2

템플릿 인스턴스화 회피를 위한 extern 템플릿 사용 (C++11)
C++11에서는 extern 템플릿 기능이 도입되었습니다. 이 기능을 사용하면 템플릿을 인스턴스화하는 것을 회피할 수 있습니다. 이번 에세이에서는 extern 템플릿의 사용 방법과 그에 따른 이점에 대해 알아보겠습니다.
처음으로 우리는 extern 템플릿이 무엇인지 이해해야 합니다. C++에서 템플릿은 강력한 기능으로, 특정 타입에 대한 코드를 일반화시킴으로써 여러 타입에 대해 동일한 동작을 수행할 수 있도록 해줍니다. 이 때, 템플릿은 사용자가 명시적으로 인스턴스화하지 않는 이상 컴파일러에 의해 필요할 때마다 인스턴스화됩니다. 일반적으로 템플릿은 헤더 파일에 정의되며, 여러 개의 소스 파일에서 해당 템플릿을 사용할 수 있습니다.
그러나 템플릿은 인스턴스화되는 과정에서 코드가 중복 생성될 수 있는 단점이 있습니다. 이는 컴파일 시간과 실행 시간에 불필요한 오버헤드를 초래합니다. 이런 경우 extern 키워드를 사용하여 템플릿의 인스턴스화를 회피할 수 있습니다. extern 템플릿은 템플릿 정의를 하나의 소스 파일에 명시적으로 인스턴스화하고, 다른 소스 파일에서는 extern 키워드를 통해 해당 인스턴스화된 템플릿을 참조합니다.
extern 템플릿을 사용하는 가장 큰 장점 중 하나는 컴파일 시간과 실행 시간의 최적화입니다. 템플릿 인스턴스화 과정은 컴파일 시간을 크게 증가시키기 때문에, extern 템플릿을 통해 이를 회피하면 컴파일 시간을 단축시킬 수 있습니다. 또한, 실행 파일의 크기도 줄어들어 실행 시간을 최적화할 수 있습니다.
또 다른 이점은 의존성 관리입니다. 템플릿 인스턴스화는 여러 소스 파일에서 이루어질 수 있기 때문에, 템플릿이 변경될 때 해당 템플릿을 사용하는 모든 소스 파일을 다시 컴파일해야 합니다. 하지만 extern 템플릿을 사용하면 템플릿을 인스턴스화하는 단일 소스 파일만 다시 컴파일할 수 있습니다. 따라서 컴파일 시간을 줄일 수 있습니다.
하지만 extern 템플릿을 사용할 때 주의할 점도 있습니다. 템플릿이 인스턴스화되지 않은 경우 해당 템플릿을 사용하는 코드는 링크 시 에러를 발생시킬 수 있습니다. 따라서 extern 템플릿을 사용할 때는 템플릿을 인스턴스화하는 소스 파일을 항상 함께 컴파일하고 링크해야 합니다.
C++11의 extern 템플릿은 템플릿 인스턴스화를 효과적으로 회피할 수 있는 기능입니다. 컴파일 시간과 실행 시간의 최적화를 도모할 수 있으며, 의존성 관리도 향상시킬 수 있습니다. 다만 주의사항을 잘 따라야 하며, 사용 시 코드를 신중하게 관리해야 합니다.
이에 대해 간결하게 설명했지만, 이 에세이가 여러분께 도움이 되길 바랍니다. extern 템플릿을 적절히 활용하여 C++ 프로그램을 개발하는데 성공하시기를 기원합니다.

반응형
Comments