#include <iostream>

void register_callback(void* f, void* data);
void invoke_callback();

template <typename T>
void my_callback(void* data) {
    T& x = *static_cast<T*>(data);
    std:: cout << "Call[T] with " << x << std::endl;
}

// Explicit instantiation:
//template void my_callback<int>(void* data);

template <typename T>
void do_register_callback(T& value) {
    // Implicit instantiation:
    if (false) { my_callback<T>(0); }
    register_callback(reinterpret_cast<void*>(static_cast<void(*)(void*)>(my_callback<T>)), &value);
}

int main() {
    int ft = 42;
    do_register_callback(ft);
    invoke_callback();
}

// [ Library ] /////////////////////////////////////////////////////////////////

struct callback_t {
    void (*f)(void*);
    void* data;
} library_callback_data;

void register_callback(void* f, void* data) {
    library_callback_data.f = reinterpret_cast<void(*)(void*)>(f);
    library_callback_data.data = data;
}

void invoke_callback() {
    (*library_callback_data.f)(library_callback_data.data);
}