#include <type_traits>
#include <utility>
#include <iostream>
template <typename...>
using void_t = void;
template <typename T, template <typename> class D, typename = void>
struct detect : std::false_type {};
template <typename T, template <typename> class D>
struct detect<T, D, void_t<D<T>>> : std::true_type {};
template <typename T>
using has_m = decltype(std::declval<T>().m());
template<typename T>
struct Derived : public T
{
void m(std::true_type) { T::m(); }
void m(std::false_type) { std::cout<<"Derived\n"; }
void m() { return m(detect<T, has_m>{}); }
};
struct Base0 { };
struct Base1 { void m() { std::cout<<"Base1\n"; } };
int main(){
Derived<Base0> d0;
d0.m(); //should print "Derived"
Derived<Base1> d1;
d1.m(); //should print "Base1"
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8dXRpbGl0eT4KI2luY2x1ZGUgPGlvc3RyZWFtPgoKCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUuLi4+CiAgICB1c2luZyB2b2lkX3QgPSB2b2lkOwogICAgCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdGVtcGxhdGUgPHR5cGVuYW1lPiBjbGFzcyBELCB0eXBlbmFtZSA9IHZvaWQ+CiAgICBzdHJ1Y3QgZGV0ZWN0IDogc3RkOjpmYWxzZV90eXBlIHt9OwogICAgCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdGVtcGxhdGUgPHR5cGVuYW1lPiBjbGFzcyBEPgogICAgc3RydWN0IGRldGVjdDxULCBELCB2b2lkX3Q8RDxUPj4+IDogc3RkOjp0cnVlX3R5cGUge307CiAgICAKICAgIHRlbXBsYXRlIDx0eXBlbmFtZSBUPgogICAgdXNpbmcgaGFzX20gPSBkZWNsdHlwZShzdGQ6OmRlY2x2YWw8VD4oKS5tKCkpOwogICAgCgogICAgdGVtcGxhdGU8dHlwZW5hbWUgVD4KICAgIHN0cnVjdCBEZXJpdmVkIDogcHVibGljIFQKICAgIHsKICAgICAgICAgdm9pZCBtKHN0ZDo6dHJ1ZV90eXBlKSB7IFQ6Om0oKTsgfQogICAgICAgICB2b2lkIG0oc3RkOjpmYWxzZV90eXBlKSB7ICBzdGQ6OmNvdXQ8PCJEZXJpdmVkXG4iOyB9CiAgICAgICAgIHZvaWQgbSgpIHsgcmV0dXJuIG0oZGV0ZWN0PFQsIGhhc19tPnt9KTsgfQogICAgfTsKCnN0cnVjdCBCYXNlMCB7IH07CnN0cnVjdCBCYXNlMSB7IHZvaWQgbSgpIHsgc3RkOjpjb3V0PDwiQmFzZTFcbiI7IH0gfTsKCmludCBtYWluKCl7CiAgRGVyaXZlZDxCYXNlMD4gZDA7CiAgZDAubSgpOyAvL3Nob3VsZCBwcmludCAiRGVyaXZlZCIKICBEZXJpdmVkPEJhc2UxPiBkMTsKICBkMS5tKCk7IC8vc2hvdWxkIHByaW50ICJCYXNlMSIKfQ==