#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";
}
I2luY2x1ZGUgPHV0aWxpdHk+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCgl0ZW1wbGF0ZTxjbGFzcy4uLj5zdHJ1Y3QgdHlwZXN7dXNpbmcgdHlwZT10eXBlczt9OwoJCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBUPgogICAgc3RydWN0IGZhc3RfY2FzdGFibGVfbGVhZiB7CiAgICAgIHZpcnR1YWwgVCogZG9fZmFzdF9jYXN0KFQqIHVudXNlZD1udWxscHRyKSB7IHJldHVybiBudWxscHRyOyB9CiAgICAgIHZpcnR1YWwgVCBjb25zdCogZG9fZmFzdF9jYXN0KFQqIHVudXNlZD1udWxscHRyKSBjb25zdCB7IHJldHVybiBudWxscHRyOyB9CiAgICAgIHZpcnR1YWwgfmZhc3RfY2FzdGFibGVfbGVhZigpIHt9CiAgICB9OwogICAgdGVtcGxhdGU8Y2xhc3MgVHVwbGU+CiAgICBzdHJ1Y3QgZmFzdF9jYXN0YWJsZTsKICAgIHRlbXBsYXRlPD4KICAgIHN0cnVjdCBmYXN0X2Nhc3RhYmxlPHR5cGVzPD4+IHsKICAgICAgdmlydHVhbCB+ZmFzdF9jYXN0YWJsZSgpIHt9CiAgICB9OwogICAgdGVtcGxhdGU8Y2xhc3MgVDAsIGNsYXNzLi4uVHM+CiAgICBzdHJ1Y3QgZmFzdF9jYXN0YWJsZTx0eXBlczxUMCwgVHMuLi4+PjoKICAgICAgZmFzdF9jYXN0YWJsZV9sZWFmPFQwPiwKICAgICAgZmFzdF9jYXN0YWJsZTx0eXBlczxUcy4uLj4+CiAgICB7fTsKICAgIHRlbXBsYXRlPGNsYXNzIFQ+IHN0cnVjdCBibG9ja19kZWR1Y3Rpb24geyB0eXBlZGVmIFQgdHlwZTsgfTsKICAgIHRlbXBsYXRlPGNsYXNzIFQ+IHVzaW5nIE5vRGVkdWN0aW9uID0gdHlwZW5hbWUgYmxvY2tfZGVkdWN0aW9uPFQ+Ojp0eXBlOwogICAgdGVtcGxhdGU8Y2xhc3MgVD4KICAgIFQqIGZhc3RfY2FzdCggTm9EZWR1Y3Rpb248ZmFzdF9jYXN0YWJsZV9sZWFmPFQ+Piogc3JjICkgewogICAgICByZXR1cm4gc3JjLT5kb19mYXN0X2Nhc3QoKTsKICAgIH0KICAgIHRlbXBsYXRlPGNsYXNzIFQ+CiAgICBUIGNvbnN0KiBmYXN0X2Nhc3QoIE5vRGVkdWN0aW9uPGZhc3RfY2FzdGFibGVfbGVhZjxUPj4gY29uc3QqIHNyYyApIHsKICAgICAgcmV0dXJuIHNyYy0+ZG9fZmFzdF9jYXN0KCk7CiAgICB9CgogICAgdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MgRD4KICAgIHN0cnVjdCBmYXN0X2Nhc3RfYWxsb3dlZCA6IHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8Ym9vbCwKICAgICAgc3RkOjppc19iYXNlX29mPFQsRD46OnZhbHVlIHx8IHN0ZDo6aXNfc2FtZTxULEQ+Ojp2YWx1ZQogICAgPiB7fTsKICAgIAogICAgdGVtcGxhdGU8Y2xhc3MgU2VsZiwgY2xhc3MgQmFzZSwgY2xhc3MgVHlwZXM+CiAgICBzdHJ1Y3QgaW1wbGVtZW50X2Zhc3RfY2FzdDsKCiAgICB0ZW1wbGF0ZTxjbGFzcyBTZWxmLCBjbGFzcyBCYXNlPgogICAgc3RydWN0IGltcGxlbWVudF9mYXN0X2Nhc3Q8U2VsZixCYXNlLHR5cGVzPD4+IDogQmFzZSB7CiAgICBwcml2YXRlOgogICAgICB0ZW1wbGF0ZTxjbGFzcywgY2xhc3MsIGNsYXNzPgogICAgICBmcmllbmQgc3RydWN0IGltcGxlbWVudF9mYXN0X2Nhc3Q7CiAgICAgIAogICAgICBTZWxmKiBkb19jYXN0X3dvcmsoc3RkOjp0cnVlX3R5cGUpIHsgcmV0dXJuIHN0YXRpY19jYXN0PFNlbGYqPih0aGlzKTsgfQogICAgICBTZWxmIGNvbnN0KiBkb19jYXN0X3dvcmsoc3RkOjp0cnVlX3R5cGUpIGNvbnN0IHsgcmV0dXJuIHN0YXRpY19jYXN0PFNlbGYgY29uc3QqPih0aGlzKTsgfQogICAgICBzdGQ6Om51bGxwdHJfdCBkb19jYXN0X3dvcmsoc3RkOjpmYWxzZV90eXBlKSB7IHJldHVybiBudWxscHRyOyB9CiAgICAgIHN0ZDo6bnVsbHB0cl90IGRvX2Nhc3Rfd29yayhzdGQ6OmZhbHNlX3R5cGUpIGNvbnN0IHsgcmV0dXJuIG51bGxwdHI7IH0KICAgIH07CiAgICAKICAgIHRlbXBsYXRlPGNsYXNzIFNlbGYsIGNsYXNzIEJhc2UsIGNsYXNzIFQwLCBjbGFzcy4uLiBUcz4KICAgIHN0cnVjdCBpbXBsZW1lbnRfZmFzdF9jYXN0PFNlbGYsQmFzZSx0eXBlczxUMCxUcy4uLj4+IDoKICAgICAgaW1wbGVtZW50X2Zhc3RfY2FzdDxTZWxmLCBCYXNlLCB0eXBlczxUcy4uLj4+CiAgICB7CiAgICBwdWJsaWM6CiAgICAgIFQwKiBkb19mYXN0X2Nhc3QoIFQwKiB1bnVzZWQgPSBudWxscHRyICkgb3ZlcnJpZGUgeyByZXR1cm4gdGhpcy0+ZG9fY2FzdF93b3JrKCBmYXN0X2Nhc3RfYWxsb3dlZDxUMCxTZWxmPigpICk7IH0KICAgICAgVDAgY29uc3QqIGRvX2Zhc3RfY2FzdCggVDAqIHVudXNlZCA9IG51bGxwdHIgKSBjb25zdCBvdmVycmlkZSB7IHJldHVybiB0aGlzLT5kb19jYXN0X3dvcmsoIGZhc3RfY2FzdF9hbGxvd2VkPFQwLFNlbGY+KCkgKTsgfQogICAgfTsKCiAgICBzdHJ1Y3QgRG9nOwogICAgc3RydWN0IENhdDsKICAgIHN0cnVjdCBNb29zZTsKICAgIHR5cGVkZWYgdHlwZXM8RG9nLCBDYXQsIE1vb3NlPiBNYW1tYWxfVHlwZXM7CgogICAgc3RydWN0IE1hbW1hbCA6IGZhc3RfY2FzdGFibGU8TWFtbWFsX1R5cGVzPgogICAge307CgogICAgc3RydWN0IENhdCA6IGltcGxlbWVudF9mYXN0X2Nhc3Q8IENhdCwgTWFtbWFsLCBNYW1tYWxfVHlwZXMgPgogICAge307CgogICAgaW50IG1haW4oKSB7CiAgICAgIENhdCBjOwogICAgICBNYW1tYWwqIG09JmM7CiAgICAgIENhdCogYzIgPSBmYXN0X2Nhc3Q8Q2F0PihtKTsKICAgICAgRG9nKiBkMiA9IGZhc3RfY2FzdDxEb2c+KG0pOwogICAgICBzdGQ6OmNvdXQgPDwgYzIgPDwgIiwiIDw8IGQyIDw8ICJcbiI7CiAgICB9Cg==