#include <iostream>
template<class T>using type=T;
template<class F>
struct callback_t;
template<class F, class Sig>
struct cast_helper_pvoid_last;
template<class F, class R, class... Args>
struct cast_helper_pvoid_last<F, R(Args...)> {
type<R(*)(Args..., void*)> operator()() const {
return [](Args... args, void* pvoid)->R {
auto* callback = static_cast<callback_t<F>*>(pvoid);
return callback->f( std::forward<Args>(args)... );
};
}
};
template<class F>
struct callback_t {
F f;
void* pvoid() { return this; }
template<class Sig>
auto pvoid_at_end()->decltype( cast_helper_pvoid_last<F, Sig>{}() ) {
return cast_helper_pvoid_last<F,Sig>{}();
}
};
template<class T>using decay_t=typename std::decay<T>::type;
template<class F>
callback_t<decay_t<F>> make_callback( F&& f ) { return {std::forward<F>(f)}; }
int main() {
int x = 3;
auto callback = make_callback( [&]( int y ) { return x+y; } );
int (*func)(int, void*) = callback.pvoid_at_end<int(int)>();
std::cout << func( 1, callback.pvoid() ) << "\n";
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGU8Y2xhc3MgVD51c2luZyB0eXBlPVQ7CnRlbXBsYXRlPGNsYXNzIEY+CnN0cnVjdCBjYWxsYmFja190OwoKdGVtcGxhdGU8Y2xhc3MgRiwgY2xhc3MgU2lnPgpzdHJ1Y3QgY2FzdF9oZWxwZXJfcHZvaWRfbGFzdDsKdGVtcGxhdGU8Y2xhc3MgRiwgY2xhc3MgUiwgY2xhc3MuLi4gQXJncz4Kc3RydWN0IGNhc3RfaGVscGVyX3B2b2lkX2xhc3Q8RiwgUihBcmdzLi4uKT4gewogIHR5cGU8UigqKShBcmdzLi4uLCB2b2lkKik+IG9wZXJhdG9yKCkoKSBjb25zdCB7CiAgICByZXR1cm4gW10oQXJncy4uLiBhcmdzLCB2b2lkKiBwdm9pZCktPlIgewogICAgICBhdXRvKiBjYWxsYmFjayA9IHN0YXRpY19jYXN0PGNhbGxiYWNrX3Q8Rj4qPihwdm9pZCk7CiAgICAgIHJldHVybiBjYWxsYmFjay0+Ziggc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uICk7CiAgICB9OwogIH0KfTsKCnRlbXBsYXRlPGNsYXNzIEY+CnN0cnVjdCBjYWxsYmFja190IHsKICBGIGY7CiAgdm9pZCogcHZvaWQoKSB7IHJldHVybiB0aGlzOyB9CgogIHRlbXBsYXRlPGNsYXNzIFNpZz4KICBhdXRvIHB2b2lkX2F0X2VuZCgpLT5kZWNsdHlwZSggY2FzdF9oZWxwZXJfcHZvaWRfbGFzdDxGLCBTaWc+e30oKSApIHsKICAgIHJldHVybiBjYXN0X2hlbHBlcl9wdm9pZF9sYXN0PEYsU2lnPnt9KCk7CiAgfQp9Owp0ZW1wbGF0ZTxjbGFzcyBUPnVzaW5nIGRlY2F5X3Q9dHlwZW5hbWUgc3RkOjpkZWNheTxUPjo6dHlwZTsKdGVtcGxhdGU8Y2xhc3MgRj4KY2FsbGJhY2tfdDxkZWNheV90PEY+PiBtYWtlX2NhbGxiYWNrKCBGJiYgZiApIHsgcmV0dXJuIHtzdGQ6OmZvcndhcmQ8Rj4oZil9OyB9CgppbnQgbWFpbigpIHsKCWludCB4ID0gMzsKCWF1dG8gY2FsbGJhY2sgPSBtYWtlX2NhbGxiYWNrKCBbJl0oIGludCB5ICkgeyByZXR1cm4geCt5OyB9ICk7CglpbnQgKCpmdW5jKShpbnQsIHZvaWQqKSA9IGNhbGxiYWNrLnB2b2lkX2F0X2VuZDxpbnQoaW50KT4oKTsKCXN0ZDo6Y291dCA8PCBmdW5jKCAxLCBjYWxsYmFjay5wdm9pZCgpICkgPDwgIlxuIjsKfQ==