I have a template member function with this signature:
template<typename T> void sync(void (*work)(T*), T context);
It can be called with a pointer to a function that accepts an argument of type T*. context is passed to that function. The implementation is this:
template<typename T> void queue::sync(void (*work)(T*), T context) {
dispatch_sync_f(_c_queue, static_cast<void*>(&context),
reinterpret_cast<dispatch_function_t>(work));
}
It uses reinterpret_cast<> and it works. The problem is that the standard doesn’t define it very well and it is very dangerous. How can I get rid of this? I tried static_cast but that gave me a compiler error:
static_castfromvoid (*)(std::__1::basic_string<char> *)todispatch_function_t(akavoid (*)(void *)) is not allowed.
dispatch_function_t is a C type and is the same as void (*)(void*).
I’m not sure I was clear enough. What dispatch_sync_f does is it calls a given callback function and passes the given context parameter to that callback function. (It does that on another thread, although that is out of the scope of this question.)
The reason this is not supported by
static_castis because it ispotentially unsafe. While a
std::string*will convert implicitely toa
void*, the two are not the same thing. The correct solution is toprovide a simple wrapper class to your function, which takes a
void*,and
static_casts it back to the desired type, and pass the address ofthis wrapper function to your function. (In practice, on modern
machines, you’ll get away with the
reinterpret_cast, since allpointers to data have the same size and format. Whether you want to cut
corners like this is up to you—but there are cases where it’s
justified. I’m just not convinced that this is one of them, given the
simple work-around.)
EDIT: One additional point: you say that
dispatch_function_tis a C type. If this is the case, the actual type if probablyextern "C" void (*)(void*), and you can only initialize it with functions that have"C"linkage. (Again, you’re likely to get away with it, but I’ve used compilers where the calling conventions were different for"C"and"C++".)