I'm currently working on a project that require me to use some linked lists.
I'm used to them but I really don't like the fact that I need to duplicate my code. Here is what i mean :
struct A {
struct A *prev;
struct A *next;
int i;
}
struct B {
struct B *prev;
struct B *next;
char *str;
}
If I want to create a function that add an element to any of my liked list i would need to do something like :
void add_A_element(struct A *list, struct A *new_element) { [...] }
void add_B_element(struct B *list, struct B *new_element) { [...] }
Here is my question, is there a way for me to have only one function for all my structures ?
I'm wondering if i could do so with an other structure like :
struct template {
struct template *prev;
struct template *next;
}
Then the function to add my element would look like :
void add_element(void *list, void *new_element)
{
struct template tmp_list = (struct template *)list;
struct template tmp_new_element = (struct template *)new_element;
for (struct template tmp = tmp_list; tmp != NULL; tmp = tmp->next) {
if (tmp->next == NULL) {
tmp->next = tmp_new_element;
tmp_new_element->prev = tmp;
break;
}
}
return;
}
Because we modify the same memory space, i guess this could work but i think some unexpected issue could happen.
I'm wondering if something that looks like a bit more like C++ template could exist in C.
Any help would be appreciate. Thanks
Edit : I managed to do it. I'm still planning on adding few things such as fifo/lifo queue but you can already get it on my Github
I've got full solution with templates (macro) in C if you'd like to have a look, links in the end. Meanwhile, let me explain how to approach that problem:
You should use container_of
strategy to abstractly traverse a linked list.
struct linked_list_head
{
struct linked_list_head * next;
struct linked_list_head * prev;
};
struct my_type {
...
struct linked_list_head head;
}
Then the code to get the next would be
struct linked_list_head next(struct linked_list_head * current) {
return current->next;
}
struct my_type next = container_of(next(¤t.head), struct my_type, head));
What is the container_of
macro?
Understanding container_of macro in the Linux kernel
If you want to see a full solution using templates implemented, I got a free to use (at your own risk) solution:
The library: https://github.com/flplv/fl-lib/blob/master/headers/linked_list.h
The Usage: https://github.com/flplv/fl-lib/blob/master/tests/test_linked_list.cpp