#include <functional>
template<class T, class RetType, class...Args>
RetType CallMemFn(T* obj, RetType(T::*func)(Args...), Args...args)
{return ((*obj).*(func))(std::forward<Args>(args)...);}
struct ConnectionHandle {};
template<class RetType, class...Args>
ConnectionHandle connect(std::function<RetType(Args...)> func)
{return {};}
template<class RetType, class...Args>
ConnectionHandle connect(RetType(*func)(Args...))
{return connect(std::function<RetType(Args...)>(func));}
template<class T, class RetType, class...Args>
struct boundthis {
typedef RetType result_type;
typedef T* thistype;
typedef RetType(*signature)(Args...);
boundthis(T* self, RetType(T::*func)(Args...)) :self(self), func(func) {}
RetType operator()(Args...args) {return CallMemFn(self,func,std::forward<Args>(args)...);}
private:
T* self;
RetType(T::*func)(Args...);
};
template<class T, class RetType, class...Args>
boundthis<T,RetType,Args...> bindthis(T* self, RetType(T::*func)(Args...))
{return boundthis<T,RetType,Args...>(self, func);}
template<class T, class RetType, class...Args>
ConnectionHandle connect(T* obj, RetType(T::*func)(Args...))
{return connect(std::function<RetType(Args...)>(bindthis(obj, func)));}
struct X
{
void memberFunction(int a, int b)
{
// do something
}
};
void globalStaticFunction(int a, int b)
{
// do something
}
int main()
{
// test instance
X x;
// connect a static function to the signal
connect(&globalStaticFunction);
// connect a member function
// here we have to use std::bind to get a std::function
connect(&x, &X::memberFunction);
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+Cgp0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcyBSZXRUeXBlLCBjbGFzcy4uLkFyZ3M+ClJldFR5cGUgQ2FsbE1lbUZuKFQqIG9iaiwgUmV0VHlwZShUOjoqZnVuYykoQXJncy4uLiksIEFyZ3MuLi5hcmdzKQp7cmV0dXJuICgoKm9iaikuKihmdW5jKSkoc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uKTt9CgpzdHJ1Y3QgQ29ubmVjdGlvbkhhbmRsZSB7fTsKCnRlbXBsYXRlPGNsYXNzIFJldFR5cGUsIGNsYXNzLi4uQXJncz4KQ29ubmVjdGlvbkhhbmRsZSBjb25uZWN0KHN0ZDo6ZnVuY3Rpb248UmV0VHlwZShBcmdzLi4uKT4gZnVuYykKe3JldHVybiB7fTt9Cgp0ZW1wbGF0ZTxjbGFzcyBSZXRUeXBlLCBjbGFzcy4uLkFyZ3M+CkNvbm5lY3Rpb25IYW5kbGUgY29ubmVjdChSZXRUeXBlKCpmdW5jKShBcmdzLi4uKSkKe3JldHVybiBjb25uZWN0KHN0ZDo6ZnVuY3Rpb248UmV0VHlwZShBcmdzLi4uKT4oZnVuYykpO30KCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFJldFR5cGUsIGNsYXNzLi4uQXJncz4Kc3RydWN0IGJvdW5kdGhpcyB7CiAgICB0eXBlZGVmIFJldFR5cGUgcmVzdWx0X3R5cGU7Cgl0eXBlZGVmIFQqIHRoaXN0eXBlOwoJdHlwZWRlZiBSZXRUeXBlKCpzaWduYXR1cmUpKEFyZ3MuLi4pOwogICAgYm91bmR0aGlzKFQqIHNlbGYsIFJldFR5cGUoVDo6KmZ1bmMpKEFyZ3MuLi4pKSA6c2VsZihzZWxmKSwgZnVuYyhmdW5jKSB7fQogICAgUmV0VHlwZSBvcGVyYXRvcigpKEFyZ3MuLi5hcmdzKSB7cmV0dXJuIENhbGxNZW1GbihzZWxmLGZ1bmMsc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uKTt9CnByaXZhdGU6CglUKiBzZWxmOwoJUmV0VHlwZShUOjoqZnVuYykoQXJncy4uLik7Cn07CnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFJldFR5cGUsIGNsYXNzLi4uQXJncz4KYm91bmR0aGlzPFQsUmV0VHlwZSxBcmdzLi4uPiBiaW5kdGhpcyhUKiBzZWxmLCBSZXRUeXBlKFQ6OipmdW5jKShBcmdzLi4uKSkKe3JldHVybiBib3VuZHRoaXM8VCxSZXRUeXBlLEFyZ3MuLi4+KHNlbGYsIGZ1bmMpO30KCnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFJldFR5cGUsIGNsYXNzLi4uQXJncz4KQ29ubmVjdGlvbkhhbmRsZSBjb25uZWN0KFQqIG9iaiwgUmV0VHlwZShUOjoqZnVuYykoQXJncy4uLikpCntyZXR1cm4gY29ubmVjdChzdGQ6OmZ1bmN0aW9uPFJldFR5cGUoQXJncy4uLik+KGJpbmR0aGlzKG9iaiwgZnVuYykpKTt9CiAgICAKICAgIApzdHJ1Y3QgWAp7CiAgICB2b2lkIG1lbWJlckZ1bmN0aW9uKGludCBhLCBpbnQgYikKICAgIHsKICAgICAgICAgLy8gZG8gc29tZXRoaW5nCiAgICB9Cn07Cgp2b2lkIGdsb2JhbFN0YXRpY0Z1bmN0aW9uKGludCBhLCBpbnQgYikKewogICAgLy8gZG8gc29tZXRoaW5nCn0KCgppbnQgbWFpbigpCnsKICAgIC8vIHRlc3QgaW5zdGFuY2UKICAgIFggeDsKCgogICAgLy8gY29ubmVjdCBhIHN0YXRpYyBmdW5jdGlvbiB0byB0aGUgc2lnbmFsCiAgICBjb25uZWN0KCZnbG9iYWxTdGF0aWNGdW5jdGlvbik7CgogICAgLy8gY29ubmVjdCBhIG1lbWJlciBmdW5jdGlvbgogICAgLy8gaGVyZSB3ZSBoYXZlIHRvIHVzZSBzdGQ6OmJpbmQgdG8gZ2V0IGEgc3RkOjpmdW5jdGlvbgogICAgY29ubmVjdCgmeCwgJlg6Om1lbWJlckZ1bmN0aW9uKTsKfQ==