2009-11-09 5 views
2

이 말을하기가 어렵습니다. 때로는 다음과 같은 수업을 볼 수 있습니다.클래스의 템플릿 조회?

template <typename T> 
class Wrapper 
{ 
public: 
    Wrapper(const T& t) : t_(t) {} 
    Wrapper(const Wrapper& w) : t_(w.t_) {} 
private: 
    T t_; 
} 

내가 알 수있는 한 합법적 인 코드입니다. 그러나 복사 생성자가 명시 적으로 const Wrapper<T>&이 필요하다고 명시하지 않고 const Wrapper&을 수락 할 수있는 이유는 무엇입니까? 템플릿 형식이 다른 경우는 무엇입니까? 클래스 정의를 사용하지 않으면이 방법으로 복사 생성자를 작성할 수 있습니까?

답변

3

가 명시 적 14.6.1/1 언어 표준에 의해 특정된다

이것은 표준의 이후 버전 ("주입 된 클래스 이름 인"의 개념을 통해) 재 모호 하였다

Within the scope of class template, when the name of the template is neither qualified nor followed by <, it is equivalent to the name of the template followed by the template-parameters enclosed in <>.

, 요점은이 동작이 문서에서 명시 적으로 철자가되어 있다는 것입니다.

질문의 두 번째 부분에 대답하기 위해이 규칙은 클래스가 아닌 메서드 정의를 작성할 때 매개 변수 선언에도 적용되지만 반환 형식 선언에는 적용되지 않습니다. 예를 들어,이 코드는

template <typename T> struct S { 
    S foo(S); 
}; 

template <typename T> S<T> S<T>::foo(S s) { 
    /* whatever */ 
} 

OK입니다하지만 당신은 방법의 정의에 반환 유형에서 <T> 비트를 제거 할 수 없습니다. 당신은 클래스 (<T>으로) 전체 이름을 사용한다, 그러나 당신은 이름 <T>을 사용하지 않아야합니다 : 특히 constructior에 관해서는

을 (. 그리고 당신은 방법의 정규화 된 이름에서 <T>을 제거 할 수 없습니다) 생성자 자체의 따라서 귀하의 경우 밖으로의 클래스 정의에 대한 짧은 형태는

template <typename T> Wrapper<T>::Wrapper<T>(const Wrapper& w) 
             ^ERROR !!! 

에 당신이 원하는 경우에도 생성자 이름으로 <T> 비트를 추가 할 수 있다는

template <typename T> Wrapper<T>::Wrapper(const Wrapper& w) : t_(w.t_) 
{ 
} 

참고가 될 것입니다 추신 이 마지막 주장은 더 많은 연구가 필요합니다. Comeau Online 컴파일러는 GCC가 오류라고 생각하는 반면 오류가 있다고 생각합니다. 나중에 다시 돌아가겠습니다.

P.P.S. ,

template <typename T> 
Wrapper<T>::Wrapper<T>(const Wrapper<T>& w) : t(w.t) {} 

을하지만 클래스 내부 : MSVC++ 2005에서 컴파일러는

+0

내가 GCC 4.4.2와 함께이 시도, 그것은 main1.cpp "로 거부 : 4 : 오류 : 생성자를 템플릿으로 사용하지 못했습니다. " 유즈넷 질문에 대한 답변을 보내 왔는데,이 내용에 대한 생각을 가지고 곧 나타납니다. –

3

기본적으로 클래스 템플릿 정의 내 당신은 템플릿 ID의 모든 매개 변수가 버전에 대한 짧은 손으로 정의되는 템플릿의 템플릿 이름를 사용할 수 있습니다.

0

클래스 이름을 사용하여 같은 템플릿 기반 클래스 내에서 Wrapper<T>을 사용하는 것과 같습니다.

0

아니, 클래스에서 당신이 작성해야 ... 경고 재미있는

warning C4812: obsolete declaration style: please use 'Wrapper<T>::Wrapper' instead 

와 후자의 선언에 대해 불평 Wrapper은 "현재 클래스"를 의미합니다.

편집 : 이것은 앤드류와 컴파일러가 생성자에 거부하는 이유에 대한 그의 연구를위한 것입니다

template <typename T> 
class Foo { 
public: 
    Foo() {} 
    Foo(const Foo& f); 
}; 

template <typename T> 
Foo<T>::Foo<T>(const Foo<T>& f) { } 

int main(int argc, char** argv) 
{ 
    Foo<int> f; 
    Foo<int> g(f); // make sure the template is instantiated 
} 
+0

매개 변수 선언에'Wrapper '을 사용할 필요가 없습니다. 'Wrapper'만으로도 충분합니다. – AnT

+1

실제로 위 내용은 잘못되었습니다. 생성자 이름 자체에 ''을 사용하는 것은 항상 불법입니다. 'Wrapper :: Wrapper (...'. – AnT

+0

언제나? MSC6에서 정상적으로 컴파일하고, gcc에 대한 액세스 권한이 없습니다, 슬프게도 – jmucchiello