1

이 질문은 a previous Q&A에 연결되어 있으며 gcc에 대한 버그 보고서 (gcc 4.5.0에서 수정 된 것으로 추정 됨)와 중첩 클래스 템플릿의 부분 특수화에 대한 일부 특성이 관련되어 있습니다.상속 된 중첩 클래스 템플릿의 부분 특수화 이해

내 설치는 (명시 적 speciliaztion은 동급 허용되지 않기 때문에, 더미 변수 트릭을 사용하여) 내가 char 부분적를 전문으로하는 중첩 된 클래스 템플릿 Inner와 클래스 Base을 가지고있다.

#include <type_traits> 
#include <iostream> 
#include <ios> 

struct Base 
{ 
    // dummy template parameter... 
    template<class U, class _ = void> struct Inner: std::true_type {}; 

    // ... to allow in-class partial specialization 
    template<class _> struct Inner<char, _>: std::false_type {}; 
}; 

지금은 내가 더 어떤 이상한 이유로 (가 여전히 부분 특수화 경우에도) 동급 할 수없는 Inner를 전문으로 할에 대한 Derived 클래스를 정의합니다.

struct Derived 
: 
    Base 
{ 
    // cannot partially specialize Inner inside Derived... 
    //template<class _> 
    //struct Inner<int, _>: std::false_type {}; 
}; 

// ... but specializing Derived::Inner at namespace scope, also specializes it for Base::Inner 
template<class _> struct Derived::Inner<int, _>: std::false_type {}; 

첫 번째 질문 : 왜 부분적으로 네임 스페이스 범위에서 Derived::Inner을 전문으로해야합니까?

는하지만 이상한 부분은 내가 모두 BaseDerived, 난 단지 Derived 위해 한 int에 대한 부분 특수화에서 Inner의 다양한 부분 특수화를 호출 할 때 또한 Base에 적용됩니다.

int main() 
{ 
    std::cout << std::boolalpha << Base::Inner<float>::value << "\n";  
    std::cout << std::boolalpha << Derived::Inner<float>::value << "\n";  

    std::cout << std::boolalpha << Base::Inner<char>::value << "\n";  
    std::cout << std::boolalpha << Derived::Inner<char>::value << "\n";  

    std::cout << std::boolalpha << Base::Inner<int>::value << "\n";  // huh??? 
    std::cout << std::boolalpha << Derived::Inner<int>::value << "\n"; // OK 
} 

두 번째 질문 : 왜에만 Derived::Inner<int> 일부 특수에도 불구하고, false 동일 Base::Inner<int>::value입니까?

Online example using gcc 4.8.0. 나는이 행동을 설명하는 표준에서 인용문을 찾고있다.

답변

1

부분 특수화는 대체 정의를 제공하는 기본 템플리트와 동일한 이름을 다시 선언해야합니다.

struct InnerDerived의 범위 내에서 작성하면 Derived::Inner으로 선언됩니다. Base::InnerDerived::Inner과 다른 이름이므로 다른 클래스를 선언합니다. Base::InnerDerived::Inner을 선언하는 선언으로 전문화하는 것은 불가능합니다.당신이 네임 스페이스 범위에서 Derived::Inner을 쓸 때

는 이름 조회는 Base::Inner에 그 이름을 확인 - 전문 분야가 같은 클래스의 모든 위치 : 당신이 Derived::Inner로 참조하는 경우에도, Base::Inner.

[temp.class.spec]

클래스 템플릿의 부분 특수화 차 때 정의 대신에 사용되는 템플릿의 다른 정의을 제공 표준에서

전문 분야의 논증은 부분 전문 분야의 논증과 일치합니다.

+0

tnx for the answer + standard quote! – TemplateRex

+0

내 기쁨! 클래스 외부에서'Derived :: Inner'의 선언이 합법적인지 또는 컴파일러 버그인지를 여전히 허용하는지 잘 모르겠습니다. – willj

1

특수화 템플릿은 다모류주의의 일부가 아닙니다.

실제로 유형을 선언하고 있습니다. 따라서 템플릿 전문화를 위해 구현 된 파생 헤더 파일을 볼 수있는 컴파일 유닛은 중첩 템플릿 클래스에 대한 전문화를 사용합니다.

컴파일러는 최상의 일치 항목을 찾으려고 시도하며 항상 기본 값보다 특수 형식을 선택합니다. 따라서 기본 유형의 범위에 액세스하려고해도 여전히 동일한 클래스입니다.

코드의 다른 부분에서 템플릿 클래스를 전문화하면 똑같은 일이 발생할 수 있습니다. 컴파일러가 가장 적합한 특성화를 선택하고, 그렇지 않은 경우 "기본값"을 취합니다.

+0

제 2 질문에 대한 답변입니다. 이것이 내가'Base '내부에서 할 수 있다고하더라도 부분적으로'Inner' 내부의'Derived'를 전문화 할 수없는 이유이기도합니다. – TemplateRex

+0

@TemplateRex 클래스가 Derived의 범위에 없기 때문에. 그것은 Base의 범위에 있습니다. 파생 된 Base :: SomeFunction()의 구현을 만들려고하는 것과 같습니다. (오버라이드 또는 오버로딩없이, 실제 구현). 구현의 범위는 Base :: ...입니다. 따라서 파생 클래스 범위에서 액세스하려는 실제 범위는 다음과 같습니다. Derived :: Base :: –