I inherited a big application that was originally written in C (but in the mean time a lot of C++ was also added to it). Because of historical reasons, the application contains a lot of void-pointers. Before you start to choke, let me explain why this was done.
The application contains many different data structures, but they are stored in 'generic' containers. Nowadays I would use templated STL containers for it, or I would give all data structures a common base class, so that the container can store pointers to the base class, but in the [good?] old C days, the only solution was to cast the struct-pointer to a void-pointer.
Additionally, there is a lot of code that works on these void-pointers, and uses very strange C constructions to emulate polymorphism in C.
I am now reworking the application, and trying to get rid of the void-pointers. Adding a common base-class to all the data structures isn't that hard (few days of work), but the problem is that the code is full of constructions like shown below.
This is an example of how data is stored:
void storeData (int datatype, void *data); // function prototype
...
Customer *myCustomer = ...;
storeData (TYPE_CUSTOMER, myCustomer);
This is an example of how data is fetched again:
Customer *myCustomer = (Customer *) fetchData (TYPE_CUSTOMER, key);
I actually want to replace all the void-pointers with some smart-pointer (reference-counted), but I can't find a trick to automate (or at least) help me to get rid of all the casts to and from void-pointers.
Any tips on how to find, replace, or interact in any possible way with these conversions?
It is also called general purpose pointer. It is not safe to delete a void pointer in C/C++ because delete needs to call the destructor of whatever object it's destroying, and it is impossible to do that if it doesn't know the type.
yes it is safe. Show activity on this post. In one case, malloc and free match, and in the other the allocated memory is returned. There are also secondary resources, and the constructor and destructor match.
The pointer to void can be used in generic functions in C because it is capable of pointing to any data type. One can assign the void pointer with any data type's address, and then assign the void pointer to any pointer without even performing some sort of explicit typecasting. So, it reduces complications in a code.
Some Interesting Facts: 1) void pointers cannot be dereferenced. For example the following program doesn't compile.
I actually want to replace all the void-pointers with some smart-pointer (reference-counted), but I can't find a trick to automate (or at least) help me to get rid of all the casts to and from void-pointers.
Such automated refactoring bears many risks.
Otherwise, sometimes I like to play tricks by making out of such void* functions the template functions. That:
void storeData (int datatype, void *data);
becomes:
template <class T>
void storeData (int datatype, T *data);
At first implement template by simply wrapping the original (renamed) function and converting the types. That might allow you to see potential problems - already by simply compiling the code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With