#include <iostream>
#include <type_traits>
struct A { void reset() { std::cout << "reset A" << std::endl; } };
struct B { void reset() { std::cout << "reset B" << std::endl; } };
struct X :public A{};
template <typename T, typename R, typename BT>
R call_if_possible_impl(T & obj, R(BT::*mf)(), std::false_type){}
template <typename T, typename R, typename BT>
R call_if_possible_impl(T & obj, R(BT::*mf)(), std::true_type)
{
return (obj.*mf)();
}
template <typename T, typename R, typename BT>
R call_if_possible(T & obj, R(BT::*mf)())
{
return call_if_possible_impl(obj, mf, typename std::is_base_of<BT, T>::type());
}
int main()
{
X x;
call_if_possible(x, &A::reset);
call_if_possible(x, &B::reset);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+CgpzdHJ1Y3QgQSAgICB7IHZvaWQgcmVzZXQoKSB7IHN0ZDo6Y291dCA8PCAicmVzZXQgQSIgPDwgc3RkOjplbmRsOyB9IH07CnN0cnVjdCBCICAgIHsgdm9pZCByZXNldCgpIHsgc3RkOjpjb3V0IDw8ICJyZXNldCBCIiA8PCBzdGQ6OmVuZGw7IH0gfTsKCnN0cnVjdCBYIDpwdWJsaWMgQXt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFIsIHR5cGVuYW1lIEJUPgpSIGNhbGxfaWZfcG9zc2libGVfaW1wbChUICYgb2JqLCBSKEJUOjoqbWYpKCksIHN0ZDo6ZmFsc2VfdHlwZSl7fQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFIsIHR5cGVuYW1lIEJUPgpSIGNhbGxfaWZfcG9zc2libGVfaW1wbChUICYgb2JqLCBSKEJUOjoqbWYpKCksIHN0ZDo6dHJ1ZV90eXBlKQp7CglyZXR1cm4gKG9iai4qbWYpKCk7Cn0KCnRlbXBsYXRlIDx0eXBlbmFtZSBULCB0eXBlbmFtZSBSLCB0eXBlbmFtZSBCVD4KUiBjYWxsX2lmX3Bvc3NpYmxlKFQgJiBvYmosIFIoQlQ6OiptZikoKSkKewoJcmV0dXJuIGNhbGxfaWZfcG9zc2libGVfaW1wbChvYmosIG1mLCB0eXBlbmFtZSBzdGQ6OmlzX2Jhc2Vfb2Y8QlQsIFQ+Ojp0eXBlKCkpOwp9CgppbnQgbWFpbigpCnsKCVggeDsKCgljYWxsX2lmX3Bvc3NpYmxlKHgsICZBOjpyZXNldCk7CgljYWxsX2lmX3Bvc3NpYmxlKHgsICZCOjpyZXNldCk7Cn0=