2016-08-08 4 views
4
struct Value { 
    using a_type = int; 
    a_type f() { return 1; } 
}; 

template<typename T> 
struct Wrapper { 
    T t; 
    auto call_f() { return t.f(); } 
}; 

int main() { 
    Wrapper<Value> w; 
    Wrapper<int> w2; 
    w.call_f(); 
} 

이 코드는 Clang 및 GCC에서 잘 컴파일됩니다. Wrapper<int>Wrapper<int>::call_f()의 반환 유형을 추론 할 수 없더라도 인스턴스화됩니다 (int::f()이 없음). w2.call_f()이 호출 될 때만 실패합니다.정의되지 않은 멤버 함수 반환 유형이있는 템플릿 인스턴스화

이 부분은 C++ 표준이며, 모든 컴파일러에서 작동 할 것으로 기대할 수 있습니까?

답변

11

예, 이것은 C++ 표준의 일부입니다.

템플릿 인스턴스화의 규칙은 길고 복잡하지만 짧은 버전은 템플릿 클래스의 멤버 함수가 필요한 경우에만 인스턴스화된다는 것입니다. 아무것도 호출하지 않거나 포인터를 가져 오거나 명시 적으로 인스턴스화하지 않으면 (그리고 아마도 내가 잊어 버린 다른 몇 가지 경우) 인스턴스화되지 않고 코드가 올바른 형식이됩니다. @dyp 지적한 바와

, 그것은 클래스 정의 ([temp.inst]/1) 인스턴스화 될 때 인스턴스화 멤버 함수만을 선언이지만 함수 정의 인 경우 리턴 타입 추론은 실시 인스턴스화 ([dcl.spec.auto]/12).

이것은 템플릿의 오버 헤드를 최소화하고 유형 요구 사항을 허용하는 데 매우 유용합니다. 그것은 당신이 같은 것을 수행 할 수 있습니다이 기능의 기본적-작도 할 T이 필요 (예를 들어, resize)

struct Foo { 
    //no default constructor 
    Foo(int); 
}; 

std::vector<Foo> foos; 

일부 std::vector 기능을하지만, 한 당신은 여전히 ​​사용할 수있는 그 함수를 호출하지 않는 한 기타 기능은 std::vector입니다.

2

예, 표준에서 보증합니다. Wrapper<T>::call_f()은 호출 될 때만 암시 적으로 인스턴스화됩니다.

$14.7.1/2 Implicit instantiation [temp.inst] : 클래스 템플릿 또는 멤버 템플릿의 멤버가 명시 적으로 인스턴스화 또는 명시 적으로 전문화되지 않는 한

, 전문화가 컨텍스트에서 참조 할 때 회원의 전문성이 암시 적으로 인스턴스화를 필요로 회원 정의 존재;

$14.7.1/8 Implicit instantiation [temp.inst] :

내재적 기능 템플릿 변수 템플릿 멤버 템플릿이 아닌 가상 멤버 함수 구성원 클래스는 클래스의 정적 데이터 부재를 인스턴스화한다 구현 템플리트 또는 constexpr if 문 ([stmt.if])의 부속 명령.