#include <iostream>
using namespace std;
#include <map>
template<typename T>
class Base
{
public:
//typedef void (T::*PFunc)(void);
//typedef void (*PHandler)(void*);
using PFunc = void (T::*)(void);
using PHandler = void(*)(void*);
using method_map_t = map< string, PHandler >;
static method_map_t& methods( ) {
static method_map_t* map_of_methods{};
if( ! map_of_methods ) map_of_methods = new method_map_t;
return *map_of_methods;
}
template<PFunc func>
static void register_method( string name ) {
methods()[name] = &Handler<func>;
}
// generic trampoline
template<PFunc func>
static void Handler( void* pInstance ) {
T* f = reinterpret_cast<T*>(pInstance);
(f ->* func)();
}
};
class Final : Base<Final>
{
public:
void Foo(){ cout << "got foo" << endl; }
void Bar(){ cout << "got bar" << endl; }
static void init(){
// register_method populates a table of "extern C" function pointers.
register_method<&Final::Foo>( "foo" ); //, static_cast<PHandler>( &Handler<&Final::Foo> ) );
register_method<&Final::Bar>( "bar" ); //, static_cast<PHandler>( &Handler<&Final::Bar> ) );
}
};
void InvokeFromC(void* inst, string name) {
Base<Final>::PHandler h = Base<Final>::methods()[name];
(*h)(inst);
}
int main() {
Final* f = new Final{};
f->init();
// simulate invoking from C
InvokeFromC( f, "foo" );
InvokeFromC( f, "bar" );
// your code goes here
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKI2luY2x1ZGUgPG1hcD4KCnRlbXBsYXRlPHR5cGVuYW1lIFQ+CmNsYXNzIEJhc2UKewpwdWJsaWM6ICAgIAogICAgLy90eXBlZGVmIHZvaWQgKFQ6OipQRnVuYykodm9pZCk7CiAgICAvL3R5cGVkZWYgdm9pZCAoKlBIYW5kbGVyKSh2b2lkKik7Cgl1c2luZyBQRnVuYyA9IHZvaWQgKFQ6OiopKHZvaWQpOwoJdXNpbmcgUEhhbmRsZXIgPSB2b2lkKCopKHZvaWQqKTsKICAgIHVzaW5nIG1ldGhvZF9tYXBfdCA9IG1hcDwgc3RyaW5nLCBQSGFuZGxlciA+OwogICAgCiAgICBzdGF0aWMgbWV0aG9kX21hcF90JiBtZXRob2RzKCApIHsKICAgICAgICBzdGF0aWMgbWV0aG9kX21hcF90KiBtYXBfb2ZfbWV0aG9kc3t9OwogICAgICAgIGlmKCAhIG1hcF9vZl9tZXRob2RzICkgbWFwX29mX21ldGhvZHMgPSBuZXcgbWV0aG9kX21hcF90OwogICAgICAgIHJldHVybiAqbWFwX29mX21ldGhvZHM7CiAgICB9CgogICAgdGVtcGxhdGU8UEZ1bmMgZnVuYz4KICAgIHN0YXRpYyB2b2lkIHJlZ2lzdGVyX21ldGhvZCggc3RyaW5nIG5hbWUgKSB7CiAgICAgICAgbWV0aG9kcygpW25hbWVdID0gJkhhbmRsZXI8ZnVuYz47CiAgICB9CgogICAgLy8gZ2VuZXJpYyB0cmFtcG9saW5lCiAgICB0ZW1wbGF0ZTxQRnVuYyBmdW5jPgogICAgc3RhdGljIHZvaWQgSGFuZGxlciggdm9pZCogcEluc3RhbmNlICkgewogICAgICAgIFQqIGYgPSByZWludGVycHJldF9jYXN0PFQqPihwSW5zdGFuY2UpOwogICAgICAgIChmIC0+KiBmdW5jKSgpOwogICAgfQp9OwoKY2xhc3MgRmluYWwgOiBCYXNlPEZpbmFsPgp7CnB1YmxpYzoKICAgIHZvaWQgRm9vKCl7IGNvdXQgPDwgImdvdCBmb28iIDw8IGVuZGw7IH0KICAgIHZvaWQgQmFyKCl7IGNvdXQgPDwgImdvdCBiYXIiIDw8IGVuZGw7IH0KICAgIAogICAgc3RhdGljIHZvaWQgaW5pdCgpewogICAgICAgIC8vIHJlZ2lzdGVyX21ldGhvZCBwb3B1bGF0ZXMgYSB0YWJsZSBvZiAiZXh0ZXJuIEMiIGZ1bmN0aW9uIHBvaW50ZXJzLgogICAgICAgIHJlZ2lzdGVyX21ldGhvZDwmRmluYWw6OkZvbz4oICJmb28iICk7IC8vLCBzdGF0aWNfY2FzdDxQSGFuZGxlcj4oICZIYW5kbGVyPCZGaW5hbDo6Rm9vPiApICk7CiAgICAgICAgcmVnaXN0ZXJfbWV0aG9kPCZGaW5hbDo6QmFyPiggImJhciIgKTsgLy8sIHN0YXRpY19jYXN0PFBIYW5kbGVyPiggJkhhbmRsZXI8JkZpbmFsOjpCYXI+ICkgKTsKICAgIH0KfTsKCnZvaWQgSW52b2tlRnJvbUModm9pZCogaW5zdCwgc3RyaW5nIG5hbWUpIHsKCUJhc2U8RmluYWw+OjpQSGFuZGxlciBoID0gQmFzZTxGaW5hbD46Om1ldGhvZHMoKVtuYW1lXTsKCSgqaCkoaW5zdCk7Cn0KCmludCBtYWluKCkgewoJRmluYWwqIGYgPSBuZXcgRmluYWx7fTsKCWYtPmluaXQoKTsKCS8vIHNpbXVsYXRlIGludm9raW5nIGZyb20gQyAKCUludm9rZUZyb21DKCBmLCAiZm9vIiApOwoJSW52b2tlRnJvbUMoIGYsICJiYXIiICk7CgkKCS8vIHlvdXIgY29kZSBnb2VzIGhlcmUKCXJldHVybiAwOwp9