Are There Practical Uses for Dynamic-Casting to Void Pointer

Are there practical uses for dynamic-casting to void pointer?

The dynamic_cast<void*>() can indeed be used to check for identity, even if dealing with multiple inheritance.

Try this code:

#include <iostream>

class B {
public:
virtual ~B() {}
};

class D1 : public B {
};

class D2 : public B {
};

class DD : public D1, public D2 {
};

namespace {
bool eq(B* b1, B* b2) {
return b1 == b2;
}

bool eqdc(B* b1, B *b2) {
return dynamic_cast<void*>(b1) == dynamic_cast<void*>(b2);
}
};

int
main() {
DD *dd = new DD();
D1 *d1 = dynamic_cast<D1*>(dd);
D2 *d2 = dynamic_cast<D2*>(dd);

std::cout << "eq: " << eq(d1, d2) << ", eqdc: " << eqdc(d1, d2) << "\n";
return 0;
}

Output:

eq: 0, eqdc: 1

When is dynamic_cast void* useful?

One common reason is to figure out whether two interfaces IA* and IB* are in fact pointers to the same underlying object. If you need that, use the cast.

IIRC, it's even possible in case of Multiple Inheritance with a repeated non-virtual base to have two IA* pointers which compare unequal, yet point to the same object - because they point to two different IA subobjects.

Safe way to dynamic cast void to a type?

The only thing you can do with a void* pointer is to cast it back to exactly the same type as the pointer that was cast to void* in the first place. The behaviour on doing anything else is undefined.

What you could do in your case is define

class Base
{
public:
virtual ~Base() = default; // make me a polymorphic type and make
// polymorphic delete safe at the same time.
};

and make this the base class for Alpha and Beta. Then pass a Base* pointer around rather than a void* one, and take your dynamic_casts directly on p.

Note further that if you declared virtual void Speak() = 0; in Base, then your code in main would become simply

int main(){ 
Base* p = new Alpha;
p->Speak();
delete p; // ToDo - have a look at std::unique_ptr
}

As a rule of thumb, casts of any kind are undesirable.

dynamic_cast from void *

dynamic_cast works only on polymorphic types, i.e. classes containing virtual functions.

In gcc you can dynamic_cast to void* but not from:

struct S
{
virtual ~S() {}
};

int main()
{
S* p = new S();
void* v = dynamic_cast<void*>(p);
S* p1 = dynamic_cast<S*>(v); // gives an error
}

dynamic_cast vs static_cast to void*

From 5.2.7 / 7:

If T is "pointer to cv void," then the result is a pointer to the most
derived object pointed to by v. Otherwise, a run-time check is applied
to see if the object pointed or referred to by v can be converted to
the type pointed or referred to by T.

So using dynamic_cast<void*>(o) you get a pointer to the first byte of the most "derived" object (if o is polymorphic).

The code the compiler generates for dynamic_cast<void *>(...) is something like:

static_cast<void*>(dynamic_cast<most_derived_type *>(...))

This property is often used for serialization.

what is the practical use of void datatype and void pointer?

In C void can't be considered a data type, it is a keyword used as a placeholder in place of a data type to show that actually there is no data.

For example consider the function void f(void);. Here the keyword void is used to mean the absence of any parameters passed and returned values.

But void *ptr; is different in meaning.

This declares a pointer without specifying which data type it is pointing to.

Is a dynamic_cast void* guaranteed to work (i.e. be equal to static_cast void* ) in the case of a non-polymorphic type?

This code doesn't compile and therefore doesn't produce any value, well-defined or otherwise. It runs afoul of

[expr.dynamic.cast]/6 Otherwise, v shall be a pointer to or a glvalue of a polymorphic type.

Passing a void* pointer and then cast in C

You are, in effect, trying to make the type of your pIn variable differ, depending on the value of the passed-in type flag. But there's no way to do that. Each variable must have exactly one type, known at compile time.

The closest you could achieve to what you're trying to do would probably be something like this:

void func(void *pSrc, float *pDst, int len, int type)
{
char *pIn = pSrc; /* char * so can do pointer arithmetic */
float *pOut = pDst;
while (len--) {
*pOut++ = (type == 0 ? *(float *)pIn : *(int *)pIn) * 2.0;

if (type == 0)
pIn += sizeof(float);
else pIn += sizeof(int);
}
}

This is kind of an ugly kludge, however. If your actual func is more complicated, it might be worth it. But if all you're doing is multiplying by 2, it would probably cleaner to just bite the bullet and use two separate functions. (Sorry, I know you said that's not what you wanted to do.)

The subexpression (type == 0 ? *(float *)pIn : *(int *)pIn) is somewhat of a jawbreaker as I've written for. (C is both celebrated, and notorious, for allowing this kind of pithiness.) You might prefer to write things out in a more "longhand" way:

void func(void *pSrc, float *pDst, int len, int type)
{
char *pIn = pSrc; /* char * so can do pointer arithmetic */
float *pOut = pDst;
while (len--) {
double inVal;

if (type == 0) {
inVal = *(float *)pIn;
pIn += sizeof(float);
} else {
inVal = *(int *)pIn;
pIn += sizeof(int);
}

*pOut++ = inVal * 2.0;
}
}

This second formulation would also make things easier and cleaner if you have more different values for type, or if you're doing more involved things with inVal.


Addendum: Here's a completely different approach. In your original problem statement, you had either an array of int, or an array of float, and you wanted to multiply every element by 2, without repeating too much code. I assume that in your actual situation, you have functions to apply that are more involved than just "multiply by 2".

If you're comfortable using function pointers, you could literally write a pair of "apply function to int" and "apply function to float" functions, with the actual do-the-work function specified separately, and exactly once. Here are the two "apply function" functions:

void apply_func_to_int(double (*func)(double), int *pSrc, float *pDst, int len)
{
for(int i = 0; i < len; i++)
pDst[i] = func(pSrc[i]);
}

void apply_func_to_float(double (*func)(double), float *pSrc, float *pDst, int len)
{
for(int i = 0; i < len; i++)
pDst[i] = func(pSrc[i]);
}

As you can see, they are very, very similar to each other — basically a copy-and-paste job — but they're both so short, the repetition isn't too objectionable.

Here is the function to apply:

double func(double x)
{
return x * 2;
}

Notice that you only have to write this function once. It accepts and returns a double, for reasonably full generality.

Putting it all together:

int main()
{
int i;
int input[3] = { 1, 2, 3 };
float output[3] = { 0 };
apply_func_to_int(func, input, output, 3);
for(i = 0; i < 3; i++) printf("%f ", output[i]); printf("\n");

float input2[3] = { 1.1, 2.2, 3.3 };
apply_func_to_float(func, input2, output, 3);
for(i = 0; i < 3; i++) printf("%f ", output[i]); printf("\n");
}

And of course you can apply other functions:

#include <math.h>

/* ... */

float input3[4] = { 2, 10, 25, 1.44 };
apply_func_to_float(sqrt, input3, output, 4);
for(i = 0; i < 4; i++) printf("%f ", output[i]); printf("\n");

What is the purpose of void pointers?

one could cast any pointer type to any pointer type

Not quite. void * is defined to convert any object pointer1 to void * and back again with an equivalent value. It does not need any cast.

In less common architectures, the size and range of some other pointers may be smaller than void *. Casting between other pointers type may lose necessary information.

void * provides a universal object pointer type.

void *p = any_object_pointer; // No casts required
any_object_pointer = p; // No casts required

char * could substitute for void *, except conversion to and from other object pointers requires casts.


OP's char b = 5; int*a = (int*)&b; risks undefined behavior as the alignment needs of int * may exceed char *.


1 Function pointers may be wider than void*. void * and other pointers are object pointers. C lacks a truly universal pointer type.



Related Topics



Leave a reply



Submit