2014-12-17 2 views
0

템플릿의 특정 측면에 대해 혼란스러워합니다. 여러 개의 소스 파일과 같은 템플릿 유형이있는 경우 템플릿의 소스 코드가 각 소스 파일에 대해 한 번 여러 번 컴파일됩니까?템플릿 Double Compilation?

예 test_two.h

#include "test_one.h" 
std::vector<char> cars::are_speeding(double speed_limit) 
{ 
    std::vector<char> ans; 
    for (int i = 0; i < speeds.size() ; i++) 
    { 
    if(speeds[i] > speed_limit) 
     ans.push_back(1); 
    else 
     ans.push_back(0); 
    } 
    return ans; 
} 

test_one.cpp

#include <vector> 
class cars: 
{ 
     std::vector<double> speeds; 
     vector<char> are_speeding(double); 
} 

test_one.h 아래

#include <vector> 
class poodle 
{ 
    std::vector<double> odor_strength; 
} 

그래서 표준 두 번 컴파일 된 벡터 헤더의 소스 코드입니다 :: 벡터 아니면 한 번?

+1

동일한 템플릿 매개 변수 유형에 대해 템플릿 인스턴스화를 한 번만 수행하면 링커가 올바르게 정렬됩니다. –

답변

2

헤더에 템플릿이 포함되어 있는지 여부에 관계없이 각각의 헤더 파일은 각 번역 단위에서 처리되어 결국 포함됩니다. 즉, 코드는 포함될 때마다 컴파일됩니다.

번역 단위에서 템플릿을 사용하는 경우 을 인스턴스화합니다. 아마도 여러분이 실제로 관심을 갖고있는 부분입니다. 즉, 여러 개의 객체 파일에 템플릿을 인스턴스화 할 수 있습니다. 오브젝트 파일에서 기호를 보면 (예 : UNIX 시스템에서는 nm -po object.o을 사용할 수 있지만 Windows에서는 libtool을 사용 하겠지만 Windows를 사용한지 오래되었습니다), 일반적으로 일부 함수 정의를 볼 수 있습니다. 서로 다른 객체 파일이 링커에 의해 결합되면 중복 정의가 파기됩니다. 즉, 의미 론적 문제를 일으키지 않습니다.

템플릿을 인스턴스화하는 데 많은 시간이 걸릴 수 있습니다. 특히 최적화가 켜져 있고 많은 인스턴스에서 동일한 인스턴스가 사용되는 경우 특히 그렇습니다. 예를 들어 IOStream 및 문자열은 자주 사용되며 일반적으로 항상 동일한 인스턴스 생성 (wchar_t 또는 char 사용)입니다. 템플릿을 구현하는 사람으로서이 템플릿을 처리하는 방법은 템플릿에 대해 extern 선언을 사용하고 적절한 번역 단위로 템플릿을 명시 적으로 인스턴스화하는 것입니다 (here이 제가 자세히 썼습니다).

+0

상황은 링크 타임 코드 생성과 함께 조금 바뀌며, 다음 표준 (2017 대상)이 적절한 모듈 시스템을 갖기를 정말로 희망합니다. – Deduplicator

+0

@Deduplicator : Modules SG가 작동하는 속도와 모듈이 2017 년 수정본을 작성한 경우 다소 혼란 스럽거나 일관성없는 방식으로 작동하는 것 같아서 놀라실 것입니다. 아직 요청한 TS가 없습니다. 긍정적 인면에서 [clang] (http://clang.llvm.org/)에는 문서화 된 [modules systems] (http://clang.llvm.org/docs/Modules.html)이 구현되어 있습니다. –

+0

각 변환 단위에서 템플릿을 인스턴스화하면 C++에서 매크로 또는 C 스타일 제네릭 함수를 더 나은 옵션으로 만들 수 있습니까? –

0

컴파일러는 템플릿을 여러 번 컴파일하지만 한 번만 링크합니다.

인라인 함수가 처리되는 것과 같은 방식입니다.

0

예, 템플릿은 일반적으로 헤더 파일에 정의되어 있으며 사용되는 각 번역 단위에서 별도로 "컴파일"(인스턴스화)됩니다. 많은 시스템에서 "동일한"객체 코드가 여러 객체 파일에서 생성되지만 링커는 최종 실행 파일이 생성 될 때 링커가이를 "축소"합니다.

아쉽게도 예를 들어 vector<int>vector<unsigned>을 사용하는 경우 원칙적으로 대부분의 기능에 대해 동일한 개체 코드를 공유 할 수 있지만 실제로는 그렇지 않습니다. 이것은 컨테이너를 만들 때 타입 소거가 더 자주 발생하는 C와 비교하여 C + +에서 명령어 캐시 낭비 또는 "부풀림"의 원인 중 하나입니다.