Comment by comex
Note that some CFI (control flow integrity) implementations will get upset if you call a function pointer with the wrong argument types:
https://gcc.godbolt.org/z/EaPqKfvne
You could get around this by using a wrapper function, at the cost of a slightly different interface:
template <typename T, void (*fn)(T *)>
void wrapper(void *d) {
fn((T *)d);
}
template <typename T, void (*fn)(T *)>
Func0 MkFunc0(T* d) {
auto res = Func0{};
res.fn = (void *)wrapper<T, fn>;
res.userData = (void*)d;
return res;
}
...
Func0 x = MkFunc0<int, my_func>(nullptr);
(This approach also requires explicitly writing the argument type. It's possible to remove the need for this, but not without the kind of complexity you're trying to avoid.)