-3

The intention is to detect whether the Template type parameter D is derived from Template type parameter B. The below code has private static methods in the class IsDerivedHelper. The question is How does the static method inside the Helper class works? It doesn't have a definition in it.

#include<iostream>
#include<type_traits>

using namespace std;

class IOne
{
private:
public:
    IOne() = delete;
    virtual void print() = 0;
};

class One :public IOne
{
public:
    One() = default;
    virtual void print()
    {
        cout << "printed from class One" << endl;
    }
};

class Two
{

};

template<typename D, typename B> class IsDerivedHelper
{
    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) };
};

void main()
{
    auto v = IsDerivedHelper<One, IOne>::Is;    // Value is 1
    // auto v = IsDerivedHelper<Two, IOne>::Is; // Value is 0
    if (v)
    {
        cout << "Is derived" << endl;
    }
    else 
    {
        cout << "Not a derived." << endl;
    }
}

Thanks in advance.

Gokul E
  • 1,356
  • 2
  • 13
  • 28
  • 1
    The book reviewed [here](https://accu.org/index.php?module=bookreviews&func=search&rid=979) has a complete explanation. Go get it. It's very illuminating, despite its age. – StoryTeller - Unslander Monica Nov 16 '17 at 17:43
  • [`using namespace std;` is a bad practice](https://stackoverflow.com/q/1452721/2176813), never use it. – tambre Nov 16 '17 at 17:49
  • Avoid asking multiple distinct questions at once. See [ask]. – tambre Nov 16 '17 at 17:49
  • 1
    FYI, C++11 has [`std::is_base_of()`](http://en.cppreference.com/w/cpp/types/is_base_of) available: "*checks if a type is derived from the other type*", so `IsDerivedHelper` is not actually needed at all: `auto v = std::is_base_of::value;` `auto v = std::is_base_of::value;` – Remy Lebeau Nov 16 '17 at 18:40

1 Answers1

1

THis works at compile time really , the core is the decision of which IsDerivedHelper::Test overload to use

this call here

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

Will return the sizeof the return value of which overload is chosen. All at compile time.

The two overloads are

   static Yes Test(B*);
    static No Test(...);

The first one is used if the argument passed is derived from B. The second one is used in any other case. ... means 'any args'

the static methods are never called, everything is evaluated at compile time.

It is a clever set of tricks

pm100
  • 48,078
  • 23
  • 82
  • 145