0

I'm dealing with a special case where I can't use dynamic_cast directly because the object is a void*. Is using first static_cast on it and then dynamic_cast (on the result of the static_cast) bad practice? Is it wrong?

Here's an example of what I'm talking about:

MyClass* CastVoidPtr(void* pVoidPtr)
{
    // casting it to MyClass so we could use dynamic_cast
    MyClass* pTemp = static_cast<MyClass*>(pVoidPtr);

    // returning the actual result that will make sure that we have a MyClass object or a nullptr
    return dynamic_cast<MyClass*>(pTemp);
}
Iosif Murariu
  • 2,019
  • 1
  • 21
  • 27
  • 3
    `pTemp` is already a `MyClass*`, what do you expect the `dynamic_cast` to do here? Your comment doesn't make sense - if `pVoidPtr` were a nullptr, then `pTemp` would be also, so you could still just return it. – Barry Feb 03 '16 at 13:11
  • if `pVoidPtr` isn't of the `MyClass` type won't `pTemp` be non-null? – Iosif Murariu Feb 03 '16 at 13:13
  • Original comment: Just to enhance @Barry's comment: `return dynamic_cast(pVoidPtr);` shall do the job. See the answers for more details. Edited comment: Oh I did not know that this wouldn't be possible. Forget my comment. – Roland Sarrazin Feb 03 '16 at 13:16
  • 2
    @RolandSarrazin You can't `dynamic_cast` a `void` pointer. – molbdnilo Feb 03 '16 at 13:17
  • 1
    @RolandSarrazin if only Bjarne would allow it :( – Iosif Murariu Feb 03 '16 at 13:18
  • @IosifMurariu No. It's a `void*`, how would the compiler know whether or not it's actually a `MyClass*`? – Barry Feb 03 '16 at 13:20

1 Answers1

3

This would depend on how the pointer got to be a void* to begin with. If it was cast to the void* from the same type as be cast to (here MyClass*), then yes, this cast is fine and works as expected;

From cppreference on static_cast:

A prvalue of type pointer to void (possibly cv-qualified) can be converted to pointer to any type. If the value of the original pointer satisfies the alignment requirement of the target type, then the resulting pointer value is unchanged, otherwise it is unspecified. Conversion of any pointer to pointer to void and back to pointer to the original (or more cv-qualified) type preserves its original value.

Using static_cast in this way is essentially saying to the compiler "I know it is this type - trust me", and the compiler obliges.

The dynamic_cast can then be evaluated after this. It is typically used to cast to a more derived type. Here, you are casting to the same type - it is not doing anything particularly useful. If the type was a more derived type (e.g. MySpecialisedClass), then it would be fine.


As it stands, the function can be simplified to:

MyClass* CastVoidPtr(void* pVoidPtr)
{
    return static_cast<MyClass*>(pVoidPtr);
}

Or to simply use a naked static_cast<>.


A side note; worth mentioning here for completeness is that reinterpret_cast has similar functionality;

Any pointer to object of type T1 can be converted to pointer to object of another type cv T2. This is exactly equivalent to static_cast<cv T2*>(static_cast<cv void*>(expression)) (which implies that if T2's alignment requirement is not stricter than T1's, the value of the pointer does not change and conversion of the resulting pointer back to its original type yields the original value). In any case, the resulting pointer may only be dereferenced safely if allowed by the type aliasing rules ...

Niall
  • 30,036
  • 10
  • 99
  • 142