Simulation of templates in C (for a queue data type) -
i' m trying implement queue
structure using c. implementation simple; queue can hold int
s , nothing else. wondering if simulate c++
templates in c
(probably using preprocessor #define
) queue
can hold data type.
note: not want use void*
. think bit risky , can cause bizarre runtime errors.
you can use subtle , ugly tricks in order create kind of templates. here's do:
creation of templated list
macro define list
i first create macro - let's call define_list(type)
- create functions list of given type. create global structure containing function pointers list's functions , have pointer global structure in each instance of list (note how similar virtual method table). kind of thing:
#define define_list(type) \ \ struct _list_##type; \ \ typedef struct \ { \ int (*is_empty)(const struct _list_##type*); \ size_t (*size)(const struct _list_##type*); \ const type (*front)(const struct _list_##type*); \ void (*push_front)(struct _list_##type*, type); \ } _list_functions_##type; \ \ typedef struct _list_elem_##type \ { \ type _data; \ struct _list_elem_##type* _next; \ } list_elem_##type; \ \ typedef struct _list_##type \ { \ size_t _size; \ list_elem_##type* _first; \ list_elem_##type* _last; \ _list_functions_##type* _functions; \ } list_##type; \ \ list_##type* new_list_##type(); \ bool list_is_empty_##type(const list_##type* list); \ size_t list_size_##type(const list_##type* list); \ const type list_front_##type(const list_##type* list); \ void list_push_front_##type(list_##type* list, type elem); \ \ bool list_is_empty_##type(const list_##type* list) \ { \ return list->_size == 0; \ } \ \ size_t list_size_##type(const list_##type* list) \ { \ return list->_size; \ } \ \ const type list_front_##type(const list_##type* list) \ { \ return list->_first->_data; \ } \ \ void list_push_front_##type(list_##type* list, type elem) \ { \ ... \ } \ \ _list_functions_##type _list_funcs_##type = { \ &list_is_empty_##type, \ &list_size_##type, \ &list_front_##type, \ &list_push_front_##type, \ }; \ \ list_##type* new_list_##type() \ { \ list_##type* res = (list_##type*) malloc(sizeof(list_##type)); \ res->_size = 0; \ res->_first = null; \ res->_functions = &_list_funcs_##type; \ return res; \ } #define list(type) \ list_##type #define new_list(type) \ new_list_##type()
generic interface
here macros call list's functions via stored function pointers:
#define is_empty(collection) \ collection->_functions->is_empty(collection) #define size(collection) \ collection->_functions->size(collection) #define front(collection) \ collection->_functions->front(collection) #define push_front(collection, elem) \ collection->_functions->push_front(collection, elem)
note if use same structure design other collections lists, you'll able use last functions collections stores pointers.
example of use
and conclude, small example of how use our new list template:
/* define data structures need */ define_list(int) define_list(float) int main() { list(int)* = new_list(int); list(float)* b = new_list(float); push_front(a, 5); push_front(b, 5.2); }
you can use amount of tricks if want have kind of templates in c, that's rather ugly (just use c++, it'll simpler). overhead 1 more pointer per instance of data structure, , 1 more indirection whenever call function (no cast done, don't have store void*
pointers, yeah \o/). hope won't ever use :p
limitations
there of course limitations since using mere text replacement macros, , not real templates.
define once
you can define each type once per compile unit, otherwise, program fail compile. can major drawback example if write library , of headers contain define_
instructions.
multi-word types
if want create list
template type made of several words (signed char
, unsigned long
, const bar
, struct foo
...) or template type pointer (char*
, void*
...), have typedef
type first.
define_list(int) /* ok */ define_list(char*) /* error: pointer */ define_list(unsigned long) /* error: several words */ typedef char* char_ptr; typedef unsigned long ulong; define_list(char_ptr) /* ok */ define_list(ulong) /* ok */
you have resort same trick if want create nested lists.
Comments
Post a Comment