2016-05-04 12 views
2

Während ich durch einige der C++ - Konzepte ging stolperte ich über std :: is_base_of Logik.Logik von std :: is_base_of in C++ 11

Googeln für Logik produziert den folgenden Code, aber ich bin nicht in der Lage, es zu verstehen.

Könnte mir jemand erklären, wie es funktioniert?

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; 
} 
+4

@KerrekSB Wo ist die SFINAE oben? – Yakk

+0

@Barry die verknüpfte Frage erklärt anderen Code. Sie sind beide Versuche auf 'is_base_of', aber die verlinkte sieht so aus, als ob sie das private Vererbungsproblem löst, während (so weit ich denke) das obige nicht funktioniert (und dadurch einfacher ist). Neeraj, möchten Sie wissen, wie 'is_base_of' in Sprache implementiert werden kann, oder möchten Sie wissen, wie der von Ihnen gepostete Code funktioniert? – Yakk

+2

@KerrekSB: Ist es? Sieht für mich wie eine grundlegende Überladungsauflösung aus. 'D *' konvertiert implizit in 'B *' iif (ish) 'B' ist eine Basis von' D'. Diese Überladung gibt einen Wert vom Typ "Yes" zurück, der dreimal so groß ist wie ein "No", für das Sie mit "sizeof" testen können. Alle anderen Fälle führen zum Aufruf der Überladung, die ein "Nein" zurückgibt. Und das i-Tüpfelchen ist, dass das Ganze in einem unbewerteten Kontext ist, so dass nichts aufgerufen wird und das Ganze als Kompilierzeitkonstante verwendet werden kann. –

Antwort

1

Wenn B eine Basisklasse von D ist, wird der Anruf Test(static_cast<D*>(0)) löst zu Yes Test(B*). Andernfalls wird es in No Test(...) aufgelöst.

Wenn B eine Basisklasse von D ist, ist der Wert von sizeof(Test(static_cast<D*>(0)))sizeof(Yes). Ansonsten ist es gleich sizeof(No).

Yes und No sind so definiert, dass sizeof(Yes) nie zu sizeof(No) gleich sein.

Wenn B eine Basisklasse von D ist,

sizeof(Test(static_cast<D*>(0))) == sizeof(Yes) 

ausgewertet true. Andernfalls wird false ausgewertet.

+0

Danke R Sahu. Sicherlich fehlen mir hier einige Grundlagen. Was ist die Rolle von 0 (Ausdruck), die im static_cast-Operator übergeben wird? – Neeraj

+2

@Neeraj Es ist eine alte Schule 'nullptr' – Yakk