#include <utility>
#include <iostream>

    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<typename Tuple>
    struct fast_castable;
    template<template<typename...>class Tuple>
    struct fast_castable<Tuple<>> {
      virtual ~fast_castable() {}
    };
    template<template<typename...>class Tuple, typename T, typename... Ts>
    struct fast_castable<Tuple<T,Ts...>>:
      fast_castable_leaf<T>,
      fast_castable<Tuple<Ts...>>
    {};
    template<typename T> struct block_deduction { typedef T type; };
    template<typename T> using NoDeduction = typename block_deduction<T>::type;
    template<typename T>
    T* fast_cast( NoDeduction<fast_castable_leaf<T>>* src ) {
      return src->do_fast_cast();
    }
    template<typename T>
    T const* fast_cast( NoDeduction<fast_castable_leaf<T>> const* src ) {
      return src->do_fast_cast();
    }

    template<typename T, typename D>
    struct fast_cast_allowed : std::integral_constant<bool,
      std::is_base_of<T,D>::value || std::is_same<T,D>::value
    > {};
    
    template<typename D, typename B, typename Tuple>
    struct implement_fast_cast;

    template<typename D, typename B, template<typename...>class Tuple>
    struct implement_fast_cast<D,B,Tuple<>> : B {};
    template<typename D, typename B, template<typename...>class Tuple, typename T, typename... Ts>
    struct implement_fast_cast<D,B,Tuple<T,Ts...>> : implement_fast_cast<D, B, Tuple<Ts...>> {
    private:
      D* do_cast_work(std::true_type) { return static_cast<D*>(this); }
      D const* do_cast_work(std::true_type) const { return static_cast<D 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; }
    public:
      T* do_fast_cast( T* unused = nullptr ) override { return do_cast_work( fast_cast_allowed<T,D>() ); }
      T const* do_fast_cast( T* unused = nullptr ) const override { return do_cast_work( fast_cast_allowed<T,D>() ); }
    };

    struct Dog;
    struct Cat;
    struct Moose;
    template<typename...>struct Types {};
    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";
    }
