Casting void pointers, depending on the data (C ++)

Basically, what I want to do, depending on some variable, is to introduce a void pointer into another data type. For example (the variable "cast" is just something to get my point):

void* ptr = some data; int temp = some data; int i = 0; ... if(temp == 32) cast = (uint32*) else if(temp == 16) cast = (uint16*) else cast = (uint8*) i = someArray[*((cast)ptr)]; 

Is there anything in C ++ that can do something like this (since you cannot assign a variable simply (uint32 *) or something like that)? I apologize if this is not clear, any help would be greatly appreciated.

0
source share
6 answers

"The right way:

 union MyUnion { uint32 asUint32; uint16 asUint16; uint8 asUint8; } uint32 to_index(int size, MyUnion* ptr) { if (size== 32) return ptr->asUint32; if (size== 16) return ptr->asUint16; if (size== 8) return ptr->asUint8; } i = someArray[to_index(temp,ptr)] 

[update: fixed dumb typo]

+5
source

Clearly, boost::variant is the way to go. It already stores a type tag, which makes it impossible for you to use the wrong type, guaranteeing this using the compiler. Here's how it works.

 typedef boost::variant<uint32_t*, uint16_t*, uint8_t*> v_type; // this will get a 32bit value, regardless of what is contained. Never overflows struct PromotingVisitor : boost::static_visitor<uint32_t> { template<typename T> uint32_t operator()(T* t) const { return *t; } }; v_type v(some_ptr); // may be either of the three pointers // automatically figures out what pointer is stored, calls operator() with // the correct type, and returns the result as an uint32_t. int i = someArray[boost::apply_visitor(PromotingVisitor(), v)]; 
+2
source

Cleaner solution:

 uint32 to_index(int temp, void* ptr) { if (temp == 32) return *((uint32*)ptr); if (temp == 16) return *((uint16*)ptr); if (temp == 8) return *((uint8*)ptr); assert(0); } i = someArray[to_index(temp,ptr)] 
+1
source

It looks like you are after combining or using Visual Studio _variant_t. Or maybe typeinfo () will be useful? (Honestly, I'm not quite sure what you are trying to do).

As for the throws, you can throw almost anything - which makes C ++ dangerous (and powerful if you're really careful).

Also note that pointer values ​​are 32-bit or 64-bit on most platforms, so you cannot save uint64 to void * on a 32-bit platform.

Finally, maybe this is what you want:

 void* p = whatever; uint32 x = (uint32)p; 

or maybe

 uint32 source = 6; void* p = &source; uint32 dest = *((uint32*)p); void* p = 
0
source

If you were blocked in using void ptr and are absolutely necessary for calling [] with different types:

 template <typename cast_to> inline int get_int_helper(someArray_t someArray, void* ptr) { return someArray[*static_cast<cast_to*>(ptr)]; } int get_int(someArray_t someArray, void* ptr, int temp) { switch ( temp ) { case 32: return get_int_helper<uint32>(someArray,ptr); case 16: return get_int_helper<uint16>(someArray,ptr); default: return get_int_helper<uint8>(someArray,ptr); } } 

However, as others have pointed out; There are probably better / other ways to do this. Most likely, any array you have does not have a multiple operator [], so it doesn’t need different types. In addition, you can use boost :: variant to conduct a differentiated type union so that you do not have to go around temp

0
source

It seems you want to save the "cast" function, which takes void * and creates an unsigned integer. So make this a function:

 std::map<int, boost::function<unsigned(*)(void*)> casts; template <typename T> unsigned cast(void* v) { return *(T*)v; } casts[32] = cast<uint32>; casts[16] = cast<uint16>; casts[8] = cast<uint8>; casts[128] = MySpecialCastFromDouble; void* foo = getFoo(); unsigned bar = casts[16](foo); 
0
source

Source: https://habr.com/ru/post/912858/


All Articles