#include <iostream>
#include <utility> //std::forward
#include <memory> //std::shared_ptr
using namespace std;
template<class C, class T, class... Args>
struct Proxy
{
shared_ptr<C> _objC;
typedef T (C::*funcptr_t)(Args...);
funcptr_t _fp;
Proxy(shared_ptr<C> objC, funcptr_t fp): _objC(objC), _fp(fp) {}
template<class... ActualArgs>
T operator()(ActualArgs&&... args)
{
return ((*_objC).*_fp)(std::forward<ActualArgs>(args)...);
}
};
template<class C, class T, class... Args>
Proxy<C,T,Args...> operator ->* (shared_ptr<C> c, T (C::*fp)(Args...))
{
return Proxy<C,T,Args...>(c, fp);
}
struct Clazz
{
int v;
Clazz(int x) : v(x) {}
int foo(int w) {return v + w;}
int bar(int x, int y) {return v * x + y;}
void baz(int* p) {*p = v * v;}
};
int main(void)
{
shared_ptr<Clazz> pObj (new Clazz(42));
auto fp1 = &Clazz::foo;
auto fp2 = &Clazz::bar;
auto fp3 = &Clazz::baz;
int q = 22;
int w;
int *pw = &w;
cout << (pObj->*fp1)(58) << endl;
cout << (pObj->*fp2)(132, q) << endl;
(pObj->*fp3)(pw);
cout << w << endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dXRpbGl0eT4JLy9zdGQ6OmZvcndhcmQKI2luY2x1ZGUgPG1lbW9yeT4JLy9zdGQ6OnNoYXJlZF9wdHIKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnRlbXBsYXRlPGNsYXNzIEMsIGNsYXNzIFQsIGNsYXNzLi4uIEFyZ3M+CnN0cnVjdCBQcm94eQp7CglzaGFyZWRfcHRyPEM+IF9vYmpDOwoJdHlwZWRlZiBUIChDOjoqZnVuY3B0cl90KShBcmdzLi4uKTsKCWZ1bmNwdHJfdCBfZnA7CgkKCVByb3h5KHNoYXJlZF9wdHI8Qz4gb2JqQywgZnVuY3B0cl90IGZwKTogX29iakMob2JqQyksIF9mcChmcCkge30KCQoJdGVtcGxhdGU8Y2xhc3MuLi4gQWN0dWFsQXJncz4KCVQgb3BlcmF0b3IoKShBY3R1YWxBcmdzJiYuLi4gYXJncykKCXsKCQlyZXR1cm4gKCgqX29iakMpLipfZnApKHN0ZDo6Zm9yd2FyZDxBY3R1YWxBcmdzPihhcmdzKS4uLik7Cgl9Cn07Cgp0ZW1wbGF0ZTxjbGFzcyBDLCBjbGFzcyBULCBjbGFzcy4uLiBBcmdzPgpQcm94eTxDLFQsQXJncy4uLj4gb3BlcmF0b3IgLT4qIChzaGFyZWRfcHRyPEM+IGMsIFQgKEM6OipmcCkoQXJncy4uLikpCnsKCXJldHVybiBQcm94eTxDLFQsQXJncy4uLj4oYywgZnApOwp9CgpzdHJ1Y3QgQ2xhenoKewoJaW50IHY7CgkKCUNsYXp6KGludCB4KSA6IHYoeCkge30KCQoJaW50IGZvbyhpbnQgdykge3JldHVybiB2ICsgdzt9CglpbnQgYmFyKGludCB4LCBpbnQgeSkge3JldHVybiB2ICogeCArIHk7fQoJdm9pZCBiYXooaW50KiBwKSB7KnAgPSB2ICogdjt9Cn07CgppbnQgbWFpbih2b2lkKQp7CglzaGFyZWRfcHRyPENsYXp6PiBwT2JqIChuZXcgQ2xhenooNDIpKTsKCQoJYXV0byBmcDEgPSAmQ2xheno6OmZvbzsKCWF1dG8gZnAyID0gJkNsYXp6OjpiYXI7CglhdXRvIGZwMyA9ICZDbGF6ejo6YmF6OwoJCglpbnQgcSA9IDIyOwoJaW50IHc7CglpbnQgKnB3ID0gJnc7CgkKCWNvdXQgPDwgKHBPYmotPipmcDEpKDU4KSA8PCBlbmRsOwoJY291dCA8PCAocE9iai0+KmZwMikoMTMyLCBxKSA8PCBlbmRsOwoJKHBPYmotPipmcDMpKHB3KTsKCWNvdXQgPDwgdyA8PCBlbmRsOwoJCglyZXR1cm4gMDsKfQo=