#include <utility>
#include <iostream>

	template<class...>struct types{using type=types;};
	
    template<typename T>
    struct fast_castable_leaf {
      virtual T* do_fast_cast(T* unused=nullptr) { return nullptr; }
      virtual T const* do_fast_cast(T* unused=nullptr) const { return nullptr; }
      virtual ~fast_castable_leaf() {}
    };
    template<class Tuple>
    struct fast_castable;
    template<>
    struct fast_castable<types<>> {
      virtual ~fast_castable() {}
    };
    template<class T0, class...Ts>
    struct fast_castable<types<T0, Ts...>>:
      fast_castable_leaf<T0>,
      fast_castable<types<Ts...>>
    {};
    template<class T> struct block_deduction { typedef T type; };
    template<class T> using NoDeduction = typename block_deduction<T>::type;
    template<class T>
    T* fast_cast( NoDeduction<fast_castable_leaf<T>>* src ) {
      return src->do_fast_cast();
    }
    template<class T>
    T const* fast_cast( NoDeduction<fast_castable_leaf<T>> const* src ) {
      return src->do_fast_cast();
    }

    template<class T, class D>
    struct fast_cast_allowed : std::integral_constant<bool,
      std::is_base_of<T,D>::value || std::is_same<T,D>::value
    > {};
    
    template<class Self, class Base, class Types>
    struct implement_fast_cast;

    template<class Self, class Base>
    struct implement_fast_cast<Self,Base,types<>> : Base {
    private:
      template<class, class, class>
      friend struct implement_fast_cast;
      
      Self* do_cast_work(std::true_type) { return static_cast<Self*>(this); }
      Self const* do_cast_work(std::true_type) const { return static_cast<Self const*>(this); }
      std::nullptr_t do_cast_work(std::false_type) { return nullptr; }
      std::nullptr_t do_cast_work(std::false_type) const { return nullptr; }
    };
    
    template<class Self, class Base, class T0, class... Ts>
    struct implement_fast_cast<Self,Base,types<T0,Ts...>> :
      implement_fast_cast<Self, Base, types<Ts...>>
    {
    public:
      T0* do_fast_cast( T0* unused = nullptr ) override { return this->do_cast_work( fast_cast_allowed<T0,Self>() ); }
      T0 const* do_fast_cast( T0* unused = nullptr ) const override { return this->do_cast_work( fast_cast_allowed<T0,Self>() ); }
    };

    struct Dog;
    struct Cat;
    struct Moose;
    typedef types<Dog, Cat, Moose> Mammal_Types;

    struct Mammal : fast_castable<Mammal_Types>
    {};

    struct Cat : implement_fast_cast< Cat, Mammal, Mammal_Types >
    {};

    int main() {
      Cat c;
      Mammal* m=&c;
      Cat* c2 = fast_cast<Cat>(m);
      Dog* d2 = fast_cast<Dog>(m);
      std::cout << c2 << "," << d2 << "\n";
    }
