From the example above I do not understand why the signature of function tfunc
is void tfunc(void* data)
and not void tfunc(class CFoo* data)
.
Anyway, it is valid to convert a pointer to any type T into a void *
, and it is valid to convert such a pointer back to T*
later. The conversion from T*
can be implicit, whereas conversion from void*
back to T*
needs to be explicit. So, in your example, tfunc(foo)
is equivalent to tfunc(static_cast<void*>(foo))
and to tfunc(dt)
.
Concerning the point "conversion of CFoo*
to void*
, there is a standard conversion (cf. this c++ online draft standard):
4 (1) Standard conversions are implicit conversions with built-in
meaning. Clause 4 enumerates the full set of such conversions.
4.10 Pointer conversions (2) A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type
“pointer to cv void”. The result of converting a non-null pointer
value of a pointer to object type to a “pointer to cv void” represents
the address of the same byte in memory as the original pointer value.
...
I'd prefer the implicit conversion over explicit conversions, as the the built-in meaning of the (implicit) standard conversion meets exactly the requirements.
A use case for void*
in a function signature could be that one wants to pass objects of unrelated type and decide inside the function to which type it has to be casted back. Suppose, for example, a function handling callbacks for different response types, and each response type might pass different (class hierarchically independent) objects:
void someCallback(int responseType, void *context) {
if(responseType == 1) {
CFoo1* foo1 = static_cast<CFoo1*>(context);
...
}
else {
CFoo2* foo2 = static_cast<CFoo2*>(context);
...
}
}