2

While going through some of the C++ concepts I stumbled upon std::is_base_of logic.

Googling around for logic produced the below code, but I am not able to understand it.

Could somebody explain me how it works?

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;
}
Neeraj Kumar
  • 836
  • 1
  • 10
  • 29
  • 4
    @KerrekSB Where is the SFINAE above? – Yakk - Adam Nevraumont May 04 '16 at 15:24
  • @Barry the linked question is explaining different code. They are both attempts at `is_base_of`, but the linked one looks like it solves the private inheritance problem, while (as far as I guess) the above one does not (and is simpler as a result). Neeraj, do you want to know how `is_base_of` can be implemented in-language, or do you want to know how the code you posted works? – Yakk - Adam Nevraumont May 04 '16 at 15:28
  • 2
    @KerrekSB: Is it? Looks like basic overload resolution to me. `D*` converts implicitly to `B*` iif (ish) `B` is a base of `D`. That overload returns a value of a type `Yes` that's three times the size of a `No`, which you can test for with `sizeof`. All other cases result in invocation of the `...` overload which returns a `No`. And the icing on the cake is that the whole thing's in an unevaluated context so nothing's actually invoked and the entire thing can be used as a compile-time constant. – Lightness Races in Orbit May 04 '16 at 15:29
  • @Yakk Yeah, but the logic behind why that `is_base_of` works also explains why this one works too - it's just more complex. – Barry May 04 '16 at 15:30
  • @Barry, I disagree with the duplicate part. The other question has very different code. – R Sahu May 04 '16 at 15:31
  • @Yakk: You're right, there's no substitution failure here. Just plain overload resolution. – Kerrek SB May 04 '16 at 15:33
  • Thanks guys for your immediate response. I am more inclined towards understanding the logic of std::is_base_of in C++11. Agree above code is not the actual implementation of std::is_base_of. I just found it over internet. – Neeraj Kumar May 04 '16 at 15:39

1 Answers1

2

When B is a base class of D, the call Test(static_cast<D*>(0)) resolves to Yes Test(B*). Otherwise, it resolves to No Test(...).

If B is a base class of D, the value of sizeof(Test(static_cast<D*>(0))) is sizeof(Yes). Otherwise, it is equal to sizeof(No).

Yes and No are defined such that sizeof(Yes) will never be equal to sizeof(No).

If B is a base class of D,

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

evaluates to true. Otherwise it evaluates to false.

R Sahu
  • 204,454
  • 14
  • 159
  • 270