2016-09-13 1 views
2

아래 코드는 실제로 std::is_base_of의 작업을 C++ 11 또는 boost::is_base_of의 기능을 수행하는 코드입니다. 도우미 함수 아래두 클래스를 템플릿 매개 변수로 사용하고 상속 된 경우 true를 반환하는 템플릿 함수를 구현하십시오.

은 동일한 작업을 수행합니다

template<typename D, typename B> 
class IsDerivedFromHelper 
{ 
    class No { }; 
    class Yes { No no[3]; }; 

    static Yes Test(B*); 
    static No Test(...); 
public: 
    enum { Is = sizeof(Test(static_cast<D*>(0))) == sizeof(Yes) }; 

}; 


template <class C, class P> 
bool IsDerivedFrom() { 
return IsDerivedFromHelper<C, P>::Is; 
} 

사람은 excatly 열거 Is이 무엇을 설명 할 수 있습니까?

무엇이 정적인가 YesTest이고 정적 인 NoTest은 무엇입니까? 함수 호출입니까?

+0

'static T f (U);''T' 형의 정적 함수'f'를 선언하고'U 형 '의 1 매개 변수를 선언합니다. –

답변

8

class No { };는 - 다른 클래스가 정의하는, 적어도 3 배 큰 것 Yes - (표준에서 요구) 제로

class Yes { No no[3]; };을하지 않습니다 정의되지 않은 크기를해야하는 클래스를 정의한다 a No. 그래서 그들은 서로 다른 크기가 보장됩니다.

static Yes Test(B*); - Yes을 반환하는 함수를 선언하지만 정의는 제공하지 않습니다 (필요하지 않습니다). B에서 파생 된 객체를 가리키는 포인터 인수와 일치합니다.

static No Test(...); - No (작음, 기억 하시겠습니까?)을 반환하는 함수를 선언하십시오. 좀 더 구체적인 것을 만족시키지 못하면 과부하가 선택됩니다. 인수를 수락합니다 (그러나 인수가 B에서 파생 된 경우 다른 버전은 기본 설정에서 과부하 해결로 선택됩니다).

sizeof(Test(static_cast<D*>(0)))D에 대한 포인터를 전달할 때 Test에 의해 반환 된 개체의 크기를 추론합니다. DB에서 파생 된 경우 Yes이고 그렇지 않은 경우 No이됩니다.

'통화'는 추론되지 않은 컨텍스트에서 이루어 지므로 평가 (호출)되지 않고 선택 만되고 반환 유형이 추론됩니다.

나머지는 아마도 자명 할 것입니다.

이이 한마디에 일을 무엇

enum { Is = sizeof(Test(static_cast<D*>(0))) == sizeof(Yes) };

은 말하고있다 :

가 "라는 상수를 선언

그래서이 모두 함께 여기에 넣어됩니다 :)되지 않았습니다 밝혀 Is이고, D*으로 Test를 호출 한 결과가 Yes과 같은 크기 일 경우 true이되며, 결과가 호출되는 유형이 ad 인 경우에는 false이됩니다 ifferent 크기. 위의 두 가지 오버로드로 인해 D가 B 또는 그 외의 파생물 인 경우 Test(D*)Yes과 동일한 크기 인 Yes을 반환하는 Yes 버전을 선택합니다. 이 과부하가 선택되지 않으면 더 관대하지만 (우선 순위는 낮습니다) 하나가됩니다. 그 사람은 No을 반환하는데, 분명히 Yes (정의)과 같은 크기는 아닙니다..? "

왜 (오버로드 확인 기준) Test(B*)보다 Test(...) '낮은 우선 순위는'그냥이기 때문에 표준이되고 그것을 정의입니다 마지막으로

:.

template <class C, class P> 
bool IsDerivedFrom() { 
return IsDerivedFromHelper<C, P>::Is; 
} 

이가를 생성 함수는 CP의 두 클래스 유형에 대해 위 테스트의 결과를 반환합니다. PC에서 파생되면 true를 반환하고 그렇지 않으면 false를 반환합니다.

+0

다른 방법이 있습니까? 크기를 비교하는 것은 약간 약해 보입니다. – pleluron

+1

@pleluron 예 여러 가지 방법이 있지만 표준에 따라 다른 크기를 요구하는 두 가지 크기를 비교하는 것은 실제로 매우 강력합니다. 현대적인 방법은 리턴 타입으로'std :: true_type'과'std :: false_type'을 사용하는 것입니다. 그것들은 각각'true'와'false' 인'value'라는 정적 멤버를 가지고 있습니다. –

+0

멋진 설명 @RichardHodges, 상속 여부를 알아 내기 위해 크기를 확인해야합니까? 또한 static_cast (0)을 설명해 주시겠습니까? 0 널 포인터입니다. 함수 호출시 추론 할 수있는 것은 무엇입니까? – LearningCpp

관련 문제