Search code examples
cpointerstemplatesstructure

Creating C "Template" function


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


Solution

  • 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(&current.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