#include <type_traits>
#include <iostream>
template< class ... >
struct make_void {
typedef void type;
};
template<class ... T>
using void_t = typename make_void< T... >::type;
template<class, class = void>
struct has_method1 : std::false_type
{};
template<class T>
struct has_method1<T, void_t<decltype(std::declval<T>().method1())>> :std::true_type
{};
template<class, class = void>
struct has_method2 : std::false_type
{};
template<class T>
struct has_method2<T, void_t<decltype(std::declval<T>().method2())>> : std::true_type
{};
template <class T>
typename std::enable_if<!has_method1<T>::value && !has_method2<T>::value>::type
Action(T&) {
std::cout << "default" << std::endl;
}
template <class T>
typename std::enable_if<!has_method1<T>::value && has_method2<T>::value>::type
Action(T& obj) {
obj.method2();
std::cout << "method2" << std::endl;
}
template <class T>
typename std::enable_if<has_method1<T>::value>::type
Action(T& obj) {
obj.method1();
std::cout << "method1" << std::endl;
}
struct Test
{};
struct Test1 {
void method1() {}
};
struct Test2 {
void method2() {}
};
struct Test12 {
void method1() {}
void method2() {}
};
int main() {
Test test;
Test1 test1;
Test2 test2;
Test12 test12;
Action(test); // default
Action(test1); // method1
Action(test2); // method2
Action(test12); // method1
return 0;
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8aW9zdHJlYW0+Cgp0ZW1wbGF0ZTwgY2xhc3MgLi4uID4Kc3RydWN0IG1ha2Vfdm9pZCB7Cgl0eXBlZGVmIHZvaWQgdHlwZTsKfTsKIAp0ZW1wbGF0ZTxjbGFzcyAuLi4gVD4KdXNpbmcgdm9pZF90ID0gdHlwZW5hbWUgbWFrZV92b2lkPCBULi4uID46OnR5cGU7Cgp0ZW1wbGF0ZTxjbGFzcywgY2xhc3MgPSB2b2lkPgpzdHJ1Y3QgaGFzX21ldGhvZDEgOiBzdGQ6OmZhbHNlX3R5cGUKe307CnRlbXBsYXRlPGNsYXNzIFQ+IApzdHJ1Y3QgaGFzX21ldGhvZDE8VCwgdm9pZF90PGRlY2x0eXBlKHN0ZDo6ZGVjbHZhbDxUPigpLm1ldGhvZDEoKSk+PiA6c3RkOjp0cnVlX3R5cGUKe307CnRlbXBsYXRlPGNsYXNzLCBjbGFzcyA9IHZvaWQ+CnN0cnVjdCBoYXNfbWV0aG9kMiA6IHN0ZDo6ZmFsc2VfdHlwZQp7fTsKdGVtcGxhdGU8Y2xhc3MgVD4Kc3RydWN0IGhhc19tZXRob2QyPFQsIHZvaWRfdDxkZWNsdHlwZShzdGQ6OmRlY2x2YWw8VD4oKS5tZXRob2QyKCkpPj4gOiBzdGQ6OnRydWVfdHlwZQp7fTsKCgp0ZW1wbGF0ZSA8Y2xhc3MgVD4KdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8IWhhc19tZXRob2QxPFQ+Ojp2YWx1ZSAmJiAhaGFzX21ldGhvZDI8VD46OnZhbHVlPjo6dHlwZQpBY3Rpb24oVCYpIHsKICAgIHN0ZDo6Y291dCA8PCAiZGVmYXVsdCIgPDwgc3RkOjplbmRsOwp9Cgp0ZW1wbGF0ZSA8Y2xhc3MgVD4KdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8IWhhc19tZXRob2QxPFQ+Ojp2YWx1ZSAmJiBoYXNfbWV0aG9kMjxUPjo6dmFsdWU+Ojp0eXBlCkFjdGlvbihUJiBvYmopIHsKICAgIG9iai5tZXRob2QyKCk7CiAgICBzdGQ6OmNvdXQgPDwgIm1ldGhvZDIiIDw8IHN0ZDo6ZW5kbDsKfQp0ZW1wbGF0ZSA8Y2xhc3MgVD4KdHlwZW5hbWUgc3RkOjplbmFibGVfaWY8aGFzX21ldGhvZDE8VD46OnZhbHVlPjo6dHlwZQpBY3Rpb24oVCYgb2JqKSB7CiAgICBvYmoubWV0aG9kMSgpOwogICAgc3RkOjpjb3V0IDw8ICJtZXRob2QxIiA8PCBzdGQ6OmVuZGw7Cn0KCnN0cnVjdCBUZXN0Cnt9OwoKc3RydWN0IFRlc3QxIHsKICAgIHZvaWQgbWV0aG9kMSgpIHt9Cn07CgpzdHJ1Y3QgVGVzdDIgewogICAgdm9pZCBtZXRob2QyKCkge30KfTsKCnN0cnVjdCBUZXN0MTIgewogICAgdm9pZCBtZXRob2QxKCkge30KICAgIHZvaWQgbWV0aG9kMigpIHt9Cn07CgppbnQgbWFpbigpIHsKICAgIFRlc3QgdGVzdDsKICAgIFRlc3QxIHRlc3QxOwogICAgVGVzdDIgdGVzdDI7CiAgICBUZXN0MTIgdGVzdDEyOwoKICAgIEFjdGlvbih0ZXN0KTsgLy8gZGVmYXVsdAogICAgQWN0aW9uKHRlc3QxKTsgLy8gbWV0aG9kMQogICAgQWN0aW9uKHRlc3QyKTsgLy8gbWV0aG9kMgogICAgQWN0aW9uKHRlc3QxMik7IC8vIG1ldGhvZDEKCiAgICByZXR1cm4gMDsKfQo=