#include <type_traits>
template<typename Func, typename Arg, typename Enable = void>
struct has_call_with_arg1 : public std::false_type {};
template<typename Func, typename Arg>
struct has_call_with_arg1<Func, Arg,
decltype(std::declval<Func&>()(std::declval<Arg&>()))>
: public std::true_type {};
namespace has_call_with_arg_impl {
template<typename F, typename A>
std::true_type test(decltype(std::declval<F&>()(std::declval<A&>()))*);
template<typename F, typename A>
std::false_type test(...);
}
template <typename Func, typename Arg>
struct has_call_with_arg2
: public decltype(has_call_with_arg_impl::test<Func,Arg>(nullptr)) {};
struct X {};
struct Y {
void operator()(X);
};
int main() {
static_assert(has_call_with_arg1<void(int), int>::value, "Line 1");
static_assert(has_call_with_arg1<Y, X>::value, "Line 2");
static_assert(!has_call_with_arg1<Y, int>::value, "Line 3");
static_assert(has_call_with_arg2<void(int), int>::value, "Line 4");
static_assert(has_call_with_arg2<Y, X>::value, "Line 5");
static_assert(!has_call_with_arg2<Y, int>::value, "Line 6");
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIEZ1bmMsIHR5cGVuYW1lIEFyZywgdHlwZW5hbWUgRW5hYmxlID0gdm9pZD4KICAgIHN0cnVjdCBoYXNfY2FsbF93aXRoX2FyZzEgOiBwdWJsaWMgc3RkOjpmYWxzZV90eXBlIHt9OwoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIEZ1bmMsIHR5cGVuYW1lIEFyZz4KICAgIHN0cnVjdCBoYXNfY2FsbF93aXRoX2FyZzE8RnVuYywgQXJnLAogICAgICAgIGRlY2x0eXBlKHN0ZDo6ZGVjbHZhbDxGdW5jJj4oKShzdGQ6OmRlY2x2YWw8QXJnJj4oKSkpPgogICAgICAgIDogcHVibGljIHN0ZDo6dHJ1ZV90eXBlIHt9OwoKICAgIG5hbWVzcGFjZSBoYXNfY2FsbF93aXRoX2FyZ19pbXBsIHsKICAgICAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBGLCB0eXBlbmFtZSBBPgogICAgICAgIHN0ZDo6dHJ1ZV90eXBlIHRlc3QoZGVjbHR5cGUoc3RkOjpkZWNsdmFsPEYmPigpKHN0ZDo6ZGVjbHZhbDxBJj4oKSkpKik7CgogICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIEYsIHR5cGVuYW1lIEE+CiAgICAgICAgc3RkOjpmYWxzZV90eXBlIHRlc3QoLi4uKTsKICAgIH0KCiAgICB0ZW1wbGF0ZSA8dHlwZW5hbWUgRnVuYywgdHlwZW5hbWUgQXJnPgogICAgc3RydWN0IGhhc19jYWxsX3dpdGhfYXJnMgogICAgICAgIDogcHVibGljIGRlY2x0eXBlKGhhc19jYWxsX3dpdGhfYXJnX2ltcGw6OnRlc3Q8RnVuYyxBcmc+KG51bGxwdHIpKSB7fTsKCnN0cnVjdCBYIHt9OwpzdHJ1Y3QgWSB7CiAgICB2b2lkIG9wZXJhdG9yKCkoWCk7Cn07CgppbnQgbWFpbigpIHsKICAgIHN0YXRpY19hc3NlcnQoaGFzX2NhbGxfd2l0aF9hcmcxPHZvaWQoaW50KSwgaW50Pjo6dmFsdWUsICJMaW5lIDEiKTsKICAgIHN0YXRpY19hc3NlcnQoaGFzX2NhbGxfd2l0aF9hcmcxPFksIFg+Ojp2YWx1ZSwgIkxpbmUgMiIpOwogICAgc3RhdGljX2Fzc2VydCghaGFzX2NhbGxfd2l0aF9hcmcxPFksIGludD46OnZhbHVlLCAiTGluZSAzIik7CiAgICBzdGF0aWNfYXNzZXJ0KGhhc19jYWxsX3dpdGhfYXJnMjx2b2lkKGludCksIGludD46OnZhbHVlLCAiTGluZSA0Iik7CiAgICBzdGF0aWNfYXNzZXJ0KGhhc19jYWxsX3dpdGhfYXJnMjxZLCBYPjo6dmFsdWUsICJMaW5lIDUiKTsKICAgIHN0YXRpY19hc3NlcnQoIWhhc19jYWxsX3dpdGhfYXJnMjxZLCBpbnQ+Ojp2YWx1ZSwgIkxpbmUgNiIpOwp9