views:

143

answers:

4

how do I cast void *something to an object in standard C++? Specifically I want want to cast void *userdata to std::map<String, void*>

Is this possible? I am trying:

//void *user_data is a parameter of this function (callback)
std::map <String, void*> user_data_n; //this line is ok
user_data_n = static_cast<std::map<String, void *>>(*user_data); //I get the errors here.

ERRORs:

Spurious '>>' user '>' to terminate a template argument list
Expected '>' before '(' token
'void *' is not a pointer-to-object type

or is there a better way to carry information about the caller object and some other parameters I can pass to void *user_data?

UPDATE:

Ass suggested by @aaa carp I changed >> to > > and the first two errors were solved. The last is strange, Why do I get that kind of message when casting it here and not when putting that object when setting the callback?

std::map<String, void*> user_data_h;
user_data_h["Object"] = this; //this is a MainController object
user_data_h["h"] = h; //h was defined as int *h
createTrackbar("trackbar_H", winName, h, 255, trackbar_handler, &user_data_h);

where createTrackbar is defined as:

int createTrackbar( const string& trackbarname, const string& winname,
int* value, int count, TrackbarCallback onChange, void* userdata);

UPDATE2:

doing this solved my problem but following the same approach, why I still get error when trying to cast objects contained in my map object?

void trackbar_handler(int value, void *user_data){
std::map <String, void*> *user_data_map;
user_data_map = reinterpret_cast<std::map<String, void *> *>(user_data); //WORKED!! ;)

MainController *controller; //the same class type I put using "this" above
controller = reinterpret_cast<MainController *>( user_data_map["Object"]); //ERROR here

int *var = reinterpret_cast<int*> (user_data_map["h"]); //ERROR also here
+6  A: 

>> should be > > and you do not want to dereference void pointer, instead cast void pointer to desired pointer type and then dereference

@casa has already provided you with answer to second problem

aaa
that solved the first 2 errors! ;) One error left ;(
nacho4d
@nac see update
aaa
The standard says "A pointer to an object can be explicitly converted to a pointer to an object of different type.65) Except that converting an rvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified. ".
Chubsdad
It also says "Objects of cv-qualified (3.9.3) or cv-unqualified type void* (pointer to void), can be used to point to objects of unknown type. A void* shall be able to hold any object pointer. A cv-qualified or cvunqualified (3.9.3) void* shall have the same representation and alignment requirements as a cv-qualified or cv-unqualified char*.". ". Therefore it is always allowed to convert a void * to any T * (but it may not be safe to use the converted value)
Chubsdad
@Chu so, is it okay for him to use static cast?
aaa
Yes. I guess it is safe if the void ptr is being converted back to it's original type ($5.2.9/10). My idea behind the above quotes was to bring out the fact that reinterpret cast of void * back to any T* is allowed because void * has the strictest alignment requirement (equal to that of char)
Chubsdad
I updated my question, please take a look. thanks
nacho4d
@Chubsdad: "void* has the strictest alignment requirements (equal to char)" should be least strict, but otherwise great research.
Tony
+1  A: 

When you're casting from a void *, your result will be a pointer too. So the map declaration should be:

std::map <String, void*> *user_data_n;

Second, you should use reinterpret_cast for such (potentially dangerous) casts:

user_data_n = reinterpret_cast<std::map<String, void *> *>(user_data);

Update:

As others suggested, you could simply use a static_cast as well.

Why do I get that kind of message when casting it here and not when putting that object when setting the callback?

Any pointer can be implicitly converted to void *, but when converting it back to a pointer of some specific type, you need an explicit cast.

why I still get error when trying to cast objects contained in my map object?

As already mentioned in the comments, you need to dereference the pointer before using the map object. You might want to define a reference instead to make things easier:

std::map <String, void*> &user_data_map =
    *(static_cast<std::map<String, void *> *>(user_data));
casablanca
I think it's okay to use static cast if you know that void pointer was in fact the type
aaa
I won't -1, but you should `static_cast`. It's perfectly safe to `static_cast` if you go back to the same type, and you gain nothing by using `reinterpret_cast`.
GMan
I updated my question, please take a look. thanks
nacho4d
+1  A: 

An noted, the >> in that line to close your template should be > > (with a space).

Also, if user_data is a void pointer, you cannot dereference it. You could cast the pointer to another pointer type with reinterpret_cast:

std::map <String, void*> *user_data_n_ptr; //note this is a pointer to a map.
user_data_n_ptr = reinterpret_cast<std::map<String, void *> *>(user_data);

This will cast the void pointer to a std::map .

You should be careful with this. void pointers shouldn't typically be thrown around in c++. There may be a better way to do what you want and avoid void * all together.

JoshD
I used one today, had to take shower afterwards. :-(
aaa
I updated my question, please take a look. thanks
nacho4d
+1  A: 

I suppose this is for serving a C callback? It might be better to have a specialized struct which keeps all those values using the exact types. That way you'd be down to one cast for the whole thing. Something like this:

struct callback_user_data {
  my_class* that;
  int number;
  callback_user_data(my_class* p, int i) : that(p), number(i) {}
};

// the callback
void my_callback(void* user_data)
{
  callback_user_data* cbud = static_cast<callback_user_data*>(user_data);
  somehow_use(cbud->that, cbud->number);
}

//call the function, passing our user data
callback_user_data cbud(this, 42);
some_function_taking_our_callback(&my_callback, &cbud);

Note that usually I have this seen (and used) this so that not a special type is passed, but only this, which has all the necessary data anyway:

// the callback
void my_callback(void* user_data)
{
  my_class* that = static_cast<my_class*>(user_data);
  that->f();
  std::cout << that->number << '\n';
}

//call the function, passing our user data
some_function_taking_our_callback(&my_callback, this);
sbi