#include <iostream>
#include <functional>
template<bool, class Ty1, class Ty2>
struct If
{
typedef Ty2 type;
};
template<class Ty1, class Ty2>
struct If<true, Ty1, Ty2>
{
typedef Ty1 type;
};
template<class... Types>
struct Arg_types
{
};
template<class Ty1>
struct Arg_types<Ty1>
{
typedef Ty1 argument_type;
};
template<class Ty1, class Ty2>
struct Arg_types<Ty1, Ty2>
{
typedef Ty1 first_argument_type;
typedef Ty2 second_argument_type;
};
template<class Ty>
struct Is_memfunptr
{
typedef std::false_type Bool_type;
};
template<class Ret, class Arg0, class... Types>
struct Is_memfunptr<Ret(Arg0::*)(Types...)> : Arg_types<Arg0 *, Types...>
{
typedef std::true_type Bool_type;
typedef Ret result_type;
typedef Arg0 Class_type;
};
template<class _Ret, class _Arg0, class... _Types>
struct Is_memfunptr<_Ret(_Arg0::*)(_Types..., ...)>
{
typedef std::true_type Bool_type;
typedef _Ret result_type;
typedef _Arg0 Class_type;
};
struct Invoker_pmf_object
{
template<class Decayed, class Ty1, class... Types2>
static auto Call(Decayed Pmf, Ty1&& Arg1, Types2&&... Args2)
-> decltype((std::forward<Ty1>(Arg1).*Pmf)(
std::forward<Types2>(Args2)...))
{
return ((std::forward<Ty1>(Arg1).*Pmf)(
std::forward<Types2>(Args2)...));
}
};
struct Invoker_pmf_pointer
{
template<class Decayed, class Ty1, class... Types2>
static auto Call(Decayed Pmf, Ty1&& Arg1, Types2&&... Args2)
-> decltype(((*std::forward<Ty1>(Arg1)).*Pmf)(
std::forward<Types2>(Args2)...))
{
return (((*std::forward<Ty1>(Arg1)).*Pmf)(
std::forward<Types2>(Args2)...));
}
};
template<class Callable, class Ty1, class Decayed = typename std::decay<Callable>::type>
struct Invoker1 : If<
std::is_base_of<
typename Is_memfunptr<Decayed>::Class_type,
typename std::decay<Ty1>::type
>::value,
Invoker_pmf_object,
Invoker_pmf_pointer>::type
{
};
template<class Callable, class... Types>
struct Invoker;
template<class Callable, class Ty1, class... Types2>
struct Invoker<Callable, Ty1, Types2...> : Invoker1<Callable, Ty1>
{
};
template<class Callable, class... Types>
inline auto Invoke(Callable&& obj, Types&&... args) -> decltype(
Invoker<Callable, Types...>::Call(std::forward<Callable>(obj), std::forward<Types>(args)...))
{
return (Invoker<Callable, Types...>::Call(
std::forward<Callable>(obj), std::forward<Types>(args)...));
}
///////////////////////////////////////////////////
class Test
{
public:
void m1(int x) { std::cout << "m1(" << x << ")\n"; };
};
int main()
{
Invoke(&Test::m1, Test(), 20);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KCnRlbXBsYXRlPGJvb2wsIGNsYXNzIFR5MSwgY2xhc3MgVHkyPgpzdHJ1Y3QgSWYKewoJdHlwZWRlZiBUeTIgdHlwZTsKfTsKCnRlbXBsYXRlPGNsYXNzIFR5MSwgY2xhc3MgVHkyPgpzdHJ1Y3QgSWY8dHJ1ZSwgVHkxLCBUeTI+CnsKCXR5cGVkZWYgVHkxIHR5cGU7Cn07Cgp0ZW1wbGF0ZTxjbGFzcy4uLiBUeXBlcz4Kc3RydWN0IEFyZ190eXBlcwp7Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBUeTE+CnN0cnVjdCBBcmdfdHlwZXM8VHkxPgp7Cgl0eXBlZGVmIFR5MSBhcmd1bWVudF90eXBlOwp9OwoKdGVtcGxhdGU8Y2xhc3MgVHkxLCBjbGFzcyBUeTI+CnN0cnVjdCBBcmdfdHlwZXM8VHkxLCBUeTI+CnsKCXR5cGVkZWYgVHkxIGZpcnN0X2FyZ3VtZW50X3R5cGU7Cgl0eXBlZGVmIFR5MiBzZWNvbmRfYXJndW1lbnRfdHlwZTsKfTsKCnRlbXBsYXRlPGNsYXNzIFR5PgpzdHJ1Y3QgSXNfbWVtZnVucHRyCnsKCXR5cGVkZWYgc3RkOjpmYWxzZV90eXBlIEJvb2xfdHlwZTsKfTsKCnRlbXBsYXRlPGNsYXNzIFJldCwgY2xhc3MgQXJnMCwgY2xhc3MuLi4gVHlwZXM+CnN0cnVjdCBJc19tZW1mdW5wdHI8UmV0KEFyZzA6OiopKFR5cGVzLi4uKT4gOiBBcmdfdHlwZXM8QXJnMCAqLCBUeXBlcy4uLj4KewoJdHlwZWRlZiBzdGQ6OnRydWVfdHlwZSBCb29sX3R5cGU7Cgl0eXBlZGVmIFJldCByZXN1bHRfdHlwZTsKCXR5cGVkZWYgQXJnMCBDbGFzc190eXBlOwp9OwoKdGVtcGxhdGU8Y2xhc3MgX1JldCwgY2xhc3MgX0FyZzAsIGNsYXNzLi4uIF9UeXBlcz4Kc3RydWN0IElzX21lbWZ1bnB0cjxfUmV0KF9BcmcwOjoqKShfVHlwZXMuLi4sIC4uLik+CnsKCXR5cGVkZWYgc3RkOjp0cnVlX3R5cGUgQm9vbF90eXBlOwoJdHlwZWRlZiBfUmV0IHJlc3VsdF90eXBlOwoJdHlwZWRlZiBfQXJnMCBDbGFzc190eXBlOwp9OwoKc3RydWN0IEludm9rZXJfcG1mX29iamVjdAp7Cgl0ZW1wbGF0ZTxjbGFzcyBEZWNheWVkLCBjbGFzcyBUeTEsIGNsYXNzLi4uIFR5cGVzMj4KCXN0YXRpYyBhdXRvIENhbGwoRGVjYXllZCBQbWYsIFR5MSYmIEFyZzEsIFR5cGVzMiYmLi4uIEFyZ3MyKQoJCS0+IGRlY2x0eXBlKChzdGQ6OmZvcndhcmQ8VHkxPihBcmcxKS4qUG1mKSgKCQkJc3RkOjpmb3J3YXJkPFR5cGVzMj4oQXJnczIpLi4uKSkKCXsKCQlyZXR1cm4gKChzdGQ6OmZvcndhcmQ8VHkxPihBcmcxKS4qUG1mKSgKCQkJc3RkOjpmb3J3YXJkPFR5cGVzMj4oQXJnczIpLi4uKSk7Cgl9Cn07CgpzdHJ1Y3QgSW52b2tlcl9wbWZfcG9pbnRlcgp7Cgl0ZW1wbGF0ZTxjbGFzcyBEZWNheWVkLCBjbGFzcyBUeTEsIGNsYXNzLi4uIFR5cGVzMj4KCXN0YXRpYyBhdXRvIENhbGwoRGVjYXllZCBQbWYsIFR5MSYmIEFyZzEsIFR5cGVzMiYmLi4uIEFyZ3MyKQoJCS0+IGRlY2x0eXBlKCgoKnN0ZDo6Zm9yd2FyZDxUeTE+KEFyZzEpKS4qUG1mKSgKCQkJc3RkOjpmb3J3YXJkPFR5cGVzMj4oQXJnczIpLi4uKSkKCXsKCQlyZXR1cm4gKCgoKnN0ZDo6Zm9yd2FyZDxUeTE+KEFyZzEpKS4qUG1mKSgKCQkJc3RkOjpmb3J3YXJkPFR5cGVzMj4oQXJnczIpLi4uKSk7Cgl9Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBDYWxsYWJsZSwgY2xhc3MgVHkxLCBjbGFzcyBEZWNheWVkID0gdHlwZW5hbWUgc3RkOjpkZWNheTxDYWxsYWJsZT46OnR5cGU+CnN0cnVjdCBJbnZva2VyMSA6IElmPAoJCXN0ZDo6aXNfYmFzZV9vZjwKCQkJdHlwZW5hbWUgSXNfbWVtZnVucHRyPERlY2F5ZWQ+OjpDbGFzc190eXBlLAoJCQl0eXBlbmFtZSBzdGQ6OmRlY2F5PFR5MT46OnR5cGUKCQk+Ojp2YWx1ZSwKCQlJbnZva2VyX3BtZl9vYmplY3QsCgkJSW52b2tlcl9wbWZfcG9pbnRlcj46OnR5cGUKewp9OwoKdGVtcGxhdGU8Y2xhc3MgQ2FsbGFibGUsIGNsYXNzLi4uIFR5cGVzPgpzdHJ1Y3QgSW52b2tlcjsKCnRlbXBsYXRlPGNsYXNzIENhbGxhYmxlLCBjbGFzcyBUeTEsIGNsYXNzLi4uIFR5cGVzMj4Kc3RydWN0IEludm9rZXI8Q2FsbGFibGUsIFR5MSwgVHlwZXMyLi4uPiA6IEludm9rZXIxPENhbGxhYmxlLCBUeTE+CnsKfTsKCnRlbXBsYXRlPGNsYXNzIENhbGxhYmxlLCBjbGFzcy4uLiBUeXBlcz4KaW5saW5lIGF1dG8gSW52b2tlKENhbGxhYmxlJiYgb2JqLCBUeXBlcyYmLi4uIGFyZ3MpIC0+IGRlY2x0eXBlKAoJSW52b2tlcjxDYWxsYWJsZSwgVHlwZXMuLi4+OjpDYWxsKHN0ZDo6Zm9yd2FyZDxDYWxsYWJsZT4ob2JqKSwgc3RkOjpmb3J3YXJkPFR5cGVzPihhcmdzKS4uLikpCnsKCXJldHVybiAoSW52b2tlcjxDYWxsYWJsZSwgVHlwZXMuLi4+OjpDYWxsKAoJCXN0ZDo6Zm9yd2FyZDxDYWxsYWJsZT4ob2JqKSwgc3RkOjpmb3J3YXJkPFR5cGVzPihhcmdzKS4uLikpOwp9CgovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KCmNsYXNzIFRlc3QKewpwdWJsaWM6Cgl2b2lkIG0xKGludCB4KSB7IHN0ZDo6Y291dCA8PCAibTEoIiA8PCB4IDw8ICIpXG4iOyB9Owp9OwoKaW50IG1haW4oKQp7CglJbnZva2UoJlRlc3Q6Om0xLCBUZXN0KCksIDIwKTsKfQ==