#include <iostream>
using namespace std;

#include <map>

template<typename T>
class Base
{
public:    
    typedef void (T::*PFunc)(void);
    typedef void (*PHandler)(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;
    }

    static void register_method( string name, PHandler handler ) {
        methods()[name] = handler;
    }

    // generic trampoline
    template<PFunc sig>
    static void Handler( void* pInstance ) {
        T* f = reinterpret_cast<T*>(pInstance);
        (f ->* sig)();
    }
};

class Final : Base<Final>
{
public:
    void Foo(){cout<<"got foo";}
    void Bar(){cout<<"got bar";}
    
    static void init(){
        // register_method populates a table of "extern C" function pointers.
        register_method( "foo", static_cast<PHandler>( &Handler<&Final::Foo> ) );
        register_method( "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" );
	
	// your code goes here
	return 0;
}