#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(&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(&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+IApzdHJ1Y3QgaGFzX21ldGhvZDE8VCwgdm9pZF90PGRlY2x0eXBlKCZUOjptZXRob2QxKT4+IDpzdGQ6OnRydWVfdHlwZQp7fTsKdGVtcGxhdGU8Y2xhc3MsIGNsYXNzID0gdm9pZD4Kc3RydWN0IGhhc19tZXRob2QyIDogc3RkOjpmYWxzZV90eXBlCnt9Owp0ZW1wbGF0ZTxjbGFzcyBUPgpzdHJ1Y3QgaGFzX21ldGhvZDI8VCwgdm9pZF90PGRlY2x0eXBlKCZUOjptZXRob2QyKT4+IDogc3RkOjp0cnVlX3R5cGUKe307CgoKdGVtcGxhdGUgPGNsYXNzIFQ+CnR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPCFoYXNfbWV0aG9kMTxUPjo6dmFsdWUgJiYgIWhhc19tZXRob2QyPFQ+Ojp2YWx1ZT46OnR5cGUKQWN0aW9uKFQmKSB7CiAgICBzdGQ6OmNvdXQgPDwgImRlZmF1bHQiIDw8IHN0ZDo6ZW5kbDsKfQoKdGVtcGxhdGUgPGNsYXNzIFQ+CnR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPCFoYXNfbWV0aG9kMTxUPjo6dmFsdWUgJiYgaGFzX21ldGhvZDI8VD46OnZhbHVlPjo6dHlwZQpBY3Rpb24oVCYgb2JqKSB7CiAgICBvYmoubWV0aG9kMigpOwogICAgc3RkOjpjb3V0IDw8ICJtZXRob2QyIiA8PCBzdGQ6OmVuZGw7Cn0KdGVtcGxhdGUgPGNsYXNzIFQ+CnR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPGhhc19tZXRob2QxPFQ+Ojp2YWx1ZT46OnR5cGUKQWN0aW9uKFQmIG9iaikgewogICAgb2JqLm1ldGhvZDEoKTsKICAgIHN0ZDo6Y291dCA8PCAibWV0aG9kMSIgPDwgc3RkOjplbmRsOwp9CgpzdHJ1Y3QgVGVzdAp7fTsKCnN0cnVjdCBUZXN0MSB7CiAgICB2b2lkIG1ldGhvZDEoKSB7fQp9OwoKc3RydWN0IFRlc3QyIHsKICAgIHZvaWQgbWV0aG9kMigpIHt9Cn07CgpzdHJ1Y3QgVGVzdDEyIHsKICAgIHZvaWQgbWV0aG9kMSgpIHt9CiAgICB2b2lkIG1ldGhvZDIoKSB7fQp9OwoKaW50IG1haW4oKSB7CiAgICBUZXN0IHRlc3Q7CiAgICBUZXN0MSB0ZXN0MTsKICAgIFRlc3QyIHRlc3QyOwogICAgVGVzdDEyIHRlc3QxMjsKCiAgICBBY3Rpb24odGVzdCk7IC8vIGRlZmF1bHQKICAgIEFjdGlvbih0ZXN0MSk7IC8vIG1ldGhvZDEKICAgIEFjdGlvbih0ZXN0Mik7IC8vIG1ldGhvZDIKICAgIEFjdGlvbih0ZXN0MTIpOyAvLyBtZXRob2QxCgogICAgcmV0dXJuIDA7Cn0K