user3165438
user3165438

Reputation: 2661

Convert void* to a dynamic type

I have a double variable i, that is converted to a void pointer named pointer:

 double i = 3; 
 void *pointer = &i;

When I like to convert the void pointer back to double I used:

 double p = *((double*) pointer); 

I would like to convert the void pointer to the type I will send as a char*:

 char* myType= typeid(i).name();//get the name of type of "i"
 int p = *((myType*) pointer); // how to implement? 

Is it possible?

Upvotes: 1

Views: 2720

Answers (3)

pqnet
pqnet

Reputation: 6608

instead of

char* myType= typeid(i).name();//get the name of type of "i"
int p = *((myType*) pointer); // how to implement? 

use

typedef decltype(i) myType;
myType p = *((myType*) pointer);

or better:

typedef decltype(i) myType;
auto p = *reinterpret_cast<myType*>(pointer);

Works with c++11 or later. If you want to decltype on older c++ compilers, it is emulated in boost.

Edit. This is probably different from what you wanted to do, which I suppose is something like this:

void myFunction(void* unknownParam) {
    typedef (realTypeOf unknownParam) RealType; // <-- this is not real c++
    RealType &a = *reinterpret_cast<RealType*>(unknownParam)
    //do stuff using 'a'
}

This is not possible in C++, but there is a reason: it doesn't make much sense. And the reason is that for myFunction to be valid the //do stuff using 'a' part should be valid for whatever type RealType ends up being. As such, it cannot rely on any feature the RealType type have: it cannot use any of its methods, it cannot use any operator, it cannot even know whether it is a class or not. Basically, you cannot do anything more with it than what you would already be able to do on a void*, so giving the type a name doesn't really help you much.

A language feature that is similar to what you want (but not quite it) is type reflection, which is not present in C++, but you can find it in language such as Java, Objective-C or C#. Basically, you ask the object itself if it has a certain method, and eventually call it. An example in Objective-C

-(void)myFunction:(id)unknownParam {
    if([unknownParam respondsToSelector:@selector(myMethod)])
        [unknownParam performSelector:@selector(myMethod)]
}

Upvotes: 2

CashCow
CashCow

Reputation: 31445

If instead of passing around void* you used some kind of variant type, you would be able to convert it back.

If you use a string to indicate the type you will need some kind of map from string to actual type. Although you can go from type to string, there is no conversion back.

Assuming you know your underlying data is always numeric in some way, there are ways to have special discrete variants that only contain numbers. The simplest would be to store a union of a 64-bit int and a double, and some flag indicating which one you have, and then a method to convert to any numeric type, asDouble(), asLong() etc.

Upvotes: 0

Evalds Urtans
Evalds Urtans

Reputation: 6704

C/C++ does not work well to interchange datatype like for example JavaScript variables Format of int value will be different than double value format (floating point) in binary

You cannot get original data type using typeid after it has been casted to void*. Also note that typeid will have different output on different OS and compilers

double dValue = 77.7;
void* pValue = &dValue;

//output "pV" / pointer void (depending on compiler and OS)
std::cout << typeid(dValue).name() << std::endl;

To cast from void* using string you can make rules like following. Or you can try to use C++ template functions in specific cases.

int iOutValue = 0;
double dOutValue = 0;

char* name = "double";
if(!strcmp(name, "int"))
{
    iOutValue = *((int*)pValue);
}
else if(!strcmp(name, "double"))
{
    dOutValue = *((double*)pValue);
}                   

Upvotes: 2

Related Questions