Using pointers, references, handles to generic datatypes, as generic and flexible as possible
- by Patrick
In my application I have lots of different data types, e.g. Car, Bicycle, Person, ... (they're actually other data types, but this is just for the example).
Since I also have quite some 'generic' code in my application, and the application was originally written in C, pointers to Car, Bicycle, Person, ... are often passed as void-pointers to these generic modules, together with an identification of the type, like this:
Car myCar;
ShowNiceDialog ((void *)&myCar, DATATYPE_CAR);
The 'ShowNiceDialog' method now uses meta-information (functions that map DATATYPE_CAR to interfaces to get the actual data out of Car) to get information of the car, based on the given data type. That way, the generic logic only has to be written once, and not every time again for every new data type.
Of course, in C++ you could make this much easier by using a common root class, like this
class RootClass
{
public:
string getName() const = 0;
};
class Car : public RootClass
{
...
};
void ShowNiceDialog (RootClass *root);
The problem is that in some cases, we don't want to store the data type in a class, but in a totally different format to save memory.
In some cases we have hundreds of millions of instances that we need to manage in the application, and we don't want to make a full class for every instance.
Suppose we have a data type with 2 characteristics:
A quantity (double, 8 bytes)
A boolean (1 byte)
Although we only need 9 bytes to store this information, putting it in a class means that we need at least 16 bytes (because of the padding), and with the v-pointer we possibly even need 24 bytes.
For hundreds of millions of instances, every byte counts (I have a 64-bit variant of the application and in some cases it needs 6 GB of memory).
The void-pointer approach has the advantage that we can almost encode anything in a void-pointer and decide how to use it if we want information from it (use it as a real pointer, as an index, ...), but at the cost of type-safety.
Templated solutions don't help since the generic logic forms quite a big part of the application, and we don't want to templatize all this. Additionally, the data model can be extended at run time, which also means that templates won't help.
Are there better (and type-safer) ways to handle this than a void-pointer?
Any references to frameworks, whitepapers, research material regarding this?