I’ m trying to implement a queue structure using C. My implementation is very simple; the queue can hold only ints and nothing else. I was wondering if I could simulate C++ templates in C(probably by using the preprocessor #define) so that my queue can hold any data type.
Note: I do not want to use void*. I think it is a bit risky and can easily cause bizarre runtime errors.
You can use subtle and ugly tricks in order to create that kind of templates. Here’s what I would do:
Creation of a templated list
Macro to define the list
I would first create a macro – let’s call it say
define_list(type)– that would create all the functions for a list of a given type. I would then create a global structure containing function pointers to all the list’s functions and then have a pointer to that global structure in each instance of the list (note how similar it is to a virtual method table). This kind of thing:Generic interface
Here are some macros that simply call the list’s functions via the stored function pointers:
Note that if you use the same structure to design other collections than lists, you’ll be able to use the last functions for any collections that stores the good pointers.
Example of use
And to conclude, a small example of how to use our new list template:
You can use that amount of tricks if you really want to have some kind of templates in C, but that’s rather ugly (just use C++, it’ll be simpler). The only overhead will be one more pointer per instance of data structure, and thus one more indirection whenever you call a function (no cast is done, you don’t have to store
void*pointers, yeah \o/). Hope you won’t ever use that :pLimitations
There are of course some limitations since we are using mere text replacement macros, and not real templates.
Define once
You can only define each type once per compile unit, otherwise, your program will fail to compile. This can be a major drawback for example if you write a library and some of your headers contain some
define_instructions.Multi-word types
If you want to create a
Listwhose template type is made of several words (signed char,unsigned long,const bar,struct foo…) or whose template type is a pointer (char*,void*…), you will have totypedefthat type first.You will have to resort to the same trick if you want to create nested lists.