データに応じて、空ポインタをキャスト(C ++)
-
06-09-2019 - |
質問
基本的に私が何をしたいのか異なるデータ型にボイドポインタをキャストするために、いくつかの変数に応じて、です。例えば(「キャスト」変数は、全体で私のポイントを得るためにだけで何かです):
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)];
(あなたが実際には(UINT32 *)または同様のものにするために変数を割り当てることができないため)このような何かを行うことができますC ++に何かありますか?私はこれが明確でない場合は、任意の助けをいただければ幸い謝罪ます。
解決
"正しい" やり方ます:
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)]
[更新:固定ダムタイポ
他のヒント
明らかに、 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)];
クリーナー液:
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)]
多分あなたは労働組合後にしているように聞こえるか、_variant_tのVisual Studioを使用している場合。それともtypeinfoの()は参考になりますか? (正直に言うと、私はあなたがやろうとしている正確に何をかなりよく分からない)。
限りキャストとして、あなたは何にでも何でもキャストすることができます - 。それはC ++の危険な(そしてあなたが本当に慎重になら強力な)
にするものですまた、あなたは32ビットプラットフォーム上でのvoid *にuint64型を保存できなかったので、そのポインタ値は、ほとんどのプラットフォームでは32ビットまたは64ビットであることに注意してください。
最後に、多分これはあなたが望むものである。
void* p = whatever;
uint32 x = (uint32)p;
または多分
uint32 source = 6;
void* p = &source;
uint32 dest = *((uint32*)p);
void* p =
あなたはボイド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);
}
}
しかし、他の人が指摘したように、それを行うには、おそらくより良い/他の方法があります。ほとんどの場合、あなたが持っているものは何でも配列[]複数の演算子を持っていないので、それはさまざまな種類を必要としません。また、あなたは一時周りを通過する必要がないように、種類の区別組合を保持するために、ブースト::バリアントを使用することができます。
あなたが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);