Reputation: 3
as I am quite new to C++ and still have to learn a lot, please bear with me and maybe some stupid questions:
Basically, I am declaring a map<wstring, int*>
, as most of the variables I am going to dereference and use are int
s (4 bytes). Unfortunately, there are rare ones being double
s (8 bytes) or short
s (2 bytes) and I don't have any influence on this. For the sake of simplicity and as I want to learn something I'd like to read all of the pointers into the same map. Here are my thoughts:
map[wstring] = (int*) short*;//or double*
Would the above work in terms of that only the beginning of the short's or double's memory address is stored in the map and not the memory's actual content?
As I know, which keys are different I would cast the pointers back to their type before dereferencing:
short = *((short*) map[wstring]); // or double = *((double*) map[wstring]);
From my point of limited knowledge this may work. I'd say that, although from the stored memory address there would normally be read 4 bytes, as this is what the map was declared for, now, by casting to short* or double*, I am saying that I'd like to read 2 or 8 bytes from the beginning of the stored address. In fact, it did work at least with shorts but I am not sure if this was just coincidence and I need to be sure.
Again, I am sorry if this is total nonsense and thanks in advance for mind enhancing answers.
Upvotes: 0
Views: 147
Reputation: 148900
You can always cast a pointer to a pointer to a different type, even if you have to pass through a void pointer. But at dereferencing time you will get garbage since you will misinterprep a memory zone.
If you have some piece of magic to know what pointers are actually short *
or double *
, you sure can do it. Here is an example :
#include<iostream>
using namespace std;
int main()
{
double b = 0.5;
short h = 10;
int i = 5;
int *t[3] = { (int *) &b, (int *)&h, &i };
cout << *((double *) (t[0])) << " " << *((short *) (t[1])) << " " << *(t[2]) << endl;
return 0;
}
gives :
0.5 10 5
And my advices are :
Upvotes: 0
Reputation: 302942
If what you want is to store a pointer to some arbitrary data, then maybe one of the simplest things to use is a tagged union like Boost.Variant:
typedef boost::variant<
int*,
double*,
short*
> SomePtr;
std::map<wstring, SomePtr> m;
That way you can store any of the pointer types safely and use the various features that the variant
type provides to get the value out (e.g. boost::apply_visitor()
). Now I'm not sure if storing pointers is a requirement or not, but this works just as well if you use it as variant<int, double, short>
.
Alternatively, if you don't want to use Boost, you can write your own version of this variant with a union
and an index:
class Variant {
union {
int* iptr;
double* dptr;
short* sptr;
};
int which;
public:
Variant(int* p): iptr(p), which(0) { }
Variant(double* p): dptr(p), which(1) { }
Variant(short* p): sptr(p), which(2) { }
// example
template <typename F>
void visit(F f) {
switch (which) {
case 0: f(iptr); break;
case 1: f(dptr); break;
case 2: f(sptr); break;
}
}
};
std::map<wstring, Variant> m;
Upvotes: 3