0

基本上我想要做的是,根据某些变量,将 void 指针转换为不同的数据类型。例如('cast' 变量只是为了表达我的观点):

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)];

C++ 中是否有任何东西可以做这样的事情(因为你实际上不能将变量分配为只是 (uint32*) 或类似的东西)?如果不清楚,我深表歉意,任何帮助将不胜感激。

4

6 回答 6

5

“正确”的方式:

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)]

[更新:修正了愚蠢的错字]

于 2009-05-27T01:40:38.723 回答
2

显然,boost::variant是要走的路。它已经存储了一个类型标记,使您无法转换为错误的类型,并在编译器的帮助下确保了这一点。下面是它的工作原理

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)];
于 2009-05-27T11:03:17.453 回答
1

更清洁的解决方案:

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)]
于 2009-05-27T01:16:51.470 回答
0

如果您被锁定使用 void ptr,并且绝对需要使用不同类型调用 []:

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);
   }
}

但是,正如其他人指出的那样;可能有更好/其他的方法来做到这一点。最有可能的是,您拥有的任何数组都没有多个运算符 [],因此它不需要不同的类型。此外,您可以使用 boost::variant 来保存类型的可区分联合,这样您就不必传递 temp

于 2009-05-27T02:42:30.533 回答
0

您似乎想要存储采用 void* 并生成无符号整数的“cast”函数。所以,让它成为一个函数:

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);
于 2009-05-28T11:33:49.593 回答
0

听起来您可能正在寻求联合,或者您正在使用 Visual Studio _variant_t。或者也许 typeinfo() 会有所帮助?(老实说,我不太确定你到底想做什么)。

至于演员表,你可以将任何东西转换成任何东西——这就是 C++ 危险的原因(如果你真的很小心的话,它会很强大)。

另外,请注意,指针值在大多数平台上都是 32 位或 64 位的,因此您无法在 32 位平台上将 uint64 存储在 void* 中。

最后,也许这就是你想要的:

void* p = whatever;

uint32 x = (uint32)p;

或者可能

uint32 source = 6;

void* p = &source;

uint32 dest = *((uint32*)p);

void* p =
于 2009-05-27T01:05:26.207 回答