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

おそらく、あなたは組合を追いかけているようです。あるいは、VisualStudioを使用している場合は_variant_tです。または、typeinfo()が役立つでしょうか?(正直なところ、あなたが何をしようとしているのか正確にはわかりません)。

キャストに関しては、ほぼすべてのものを何にでもキャストできます。これが、C ++を危険なものにします(そして、本当に注意すれば強力です)。

また、ほとんどのプラットフォームではポインタ値が32ビットまたは64ビットであるため、32ビットプラットフォームのvoid*にuint64を格納できないことに注意してください。

最後に、多分これはあなたが望むものです:

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 に答える
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);
   }
}

しかし、他の人が指摘しているように、おそらくそれを行うためのより良い/他の方法があります。ほとんどの場合、どの配列にも複数のoperator []がないため、異なる型は必要ありません。さらに、boost :: Variantを使用して、タイプの識別された共用体を保持できるため、臨時雇用者を回す必要がありません。

于 2009-05-27T02:42:30.533 に答える
0

void *を取り、符号なし整数を生成する「キャスト」関数を格納したいようです。それで、それを関数にします:

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 に答える