#include <iostream>
#include <utility>
#include <type_traits>
namespace detail {
template<typename T>
class has_noarg_foo_method {
using yes = char(&)[1];
using no = char(&)[2];
template<typename>
struct helper;
template<typename>
static no check(...);
template<typename U>
static yes check(helper<decltype(std::declval<U>().foo())> *);
public:
static constexpr bool value = sizeof (check<T>(nullptr)) == sizeof (yes);
};
}
template<typename T>
struct has_noarg_foo_method : std::integral_constant<bool, detail::has_noarg_foo_method<T>::value> {};
struct one {
void foo() const {
std::cout << "foo()" << std::endl;
}
};
struct two {
void foo(int x) const {
std::cout << "foo(" << x << ")" << std::endl;
}
};
namespace detail {
enum class enabler;
}
template<typename T>
using enable_if = typename std::enable_if<T::value, detail::enabler>::type;
template<typename T>
using disable_if = typename std::enable_if<!T::value, detail::enabler>::type;
template<typename T, enable_if<has_noarg_foo_method<T>>...>
void do_foo(T const& obj, int) {
obj.foo();
}
template<typename T, disable_if<has_noarg_foo_method<T>>...>
void do_foo(T const& obj, int const x) {
obj.foo(x);
}
int main() {
do_foo(one{}, 1);
do_foo(two{}, 2);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dXRpbGl0eT4KI2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKCm5hbWVzcGFjZSBkZXRhaWwgewoKdGVtcGxhdGU8dHlwZW5hbWUgVD4KY2xhc3MgaGFzX25vYXJnX2Zvb19tZXRob2QgewoJCgl1c2luZyB5ZXMgPSBjaGFyKCYpWzFdOwoJdXNpbmcgbm8gID0gY2hhcigmKVsyXTsKCQoJdGVtcGxhdGU8dHlwZW5hbWU+CglzdHJ1Y3QgaGVscGVyOwoJCgl0ZW1wbGF0ZTx0eXBlbmFtZT4KCXN0YXRpYyBubyAgY2hlY2soLi4uKTsKCQoJdGVtcGxhdGU8dHlwZW5hbWUgVT4KCXN0YXRpYyB5ZXMgY2hlY2soaGVscGVyPGRlY2x0eXBlKHN0ZDo6ZGVjbHZhbDxVPigpLmZvbygpKT4gKik7CgpwdWJsaWM6CiAgIHN0YXRpYyBjb25zdGV4cHIgYm9vbCB2YWx1ZSA9IHNpemVvZiAoY2hlY2s8VD4obnVsbHB0cikpID09IHNpemVvZiAoeWVzKTsKfTsKCn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnN0cnVjdCBoYXNfbm9hcmdfZm9vX21ldGhvZCA6IHN0ZDo6aW50ZWdyYWxfY29uc3RhbnQ8Ym9vbCwgZGV0YWlsOjpoYXNfbm9hcmdfZm9vX21ldGhvZDxUPjo6dmFsdWU+IHt9OwoKCnN0cnVjdCBvbmUgewoJCiAgIHZvaWQgZm9vKCkgY29uc3QgewogICAgICBzdGQ6OmNvdXQgPDwgImZvbygpIiA8PCBzdGQ6OmVuZGw7CiAgIH0KfTsKCnN0cnVjdCB0d28gewoJCiAgIHZvaWQgZm9vKGludCB4KSBjb25zdCB7CiAgICAgIHN0ZDo6Y291dCA8PCAiZm9vKCIgPDwgeCA8PCAiKSIgPDwgc3RkOjplbmRsOwogICB9Cn07CgpuYW1lc3BhY2UgZGV0YWlsIHsKCQplbnVtIGNsYXNzIGVuYWJsZXI7Cgp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgp1c2luZyBlbmFibGVfaWYgPSB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjxUOjp2YWx1ZSwgZGV0YWlsOjplbmFibGVyPjo6dHlwZTsKCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CnVzaW5nIGRpc2FibGVfaWYgPSB0eXBlbmFtZSBzdGQ6OmVuYWJsZV9pZjwhVDo6dmFsdWUsIGRldGFpbDo6ZW5hYmxlcj46OnR5cGU7Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBULCBlbmFibGVfaWY8aGFzX25vYXJnX2Zvb19tZXRob2Q8VD4+Li4uPgp2b2lkIGRvX2ZvbyhUIGNvbnN0JiBvYmosIGludCkgewogICBvYmouZm9vKCk7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQsIGRpc2FibGVfaWY8aGFzX25vYXJnX2Zvb19tZXRob2Q8VD4+Li4uPgp2b2lkIGRvX2ZvbyhUIGNvbnN0JiBvYmosIGludCBjb25zdCB4KSB7CiAgIG9iai5mb28oeCk7Cn0KCgppbnQgbWFpbigpIHsKICAgZG9fZm9vKG9uZXt9LCAxKTsKICAgZG9fZm9vKHR3b3t9LCAyKTsKfQ==