Generics in C

Our first program will demonstrate the concept of generics in C. Here’s the full source code:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// Generic function to find the index of an element in an array
#define SlicesIndex(type, arr, size, value) ({ \
    int index = -1; \
    for (int i = 0; i < size; i++) { \
        if (arr[i] == value) { \
            index = i; \
            break; \
        } \
    } \
    index; \
})

// Generic linked list structure
#define DEFINE_LIST(T) \
    typedef struct Node_##T { \
        T value; \
        struct Node_##T* next; \
    } Node_##T; \
    \
    typedef struct { \
        Node_##T* head; \
        Node_##T* tail; \
    } List_##T; \
    \
    void Push_##T(List_##T* list, T value) { \
        Node_##T* new_node = malloc(sizeof(Node_##T)); \
        new_node->value = value; \
        new_node->next = NULL; \
        if (list->tail == NULL) { \
            list->head = list->tail = new_node; \
        } else { \
            list->tail->next = new_node; \
            list->tail = new_node; \
        } \
    } \
    \
    T* AllElements_##T(List_##T* list) { \
        int size = 0; \
        Node_##T* current = list->head; \
        while (current != NULL) { \
            size++; \
            current = current->next; \
        } \
        T* elements = malloc(size * sizeof(T)); \
        current = list->head; \
        for (int i = 0; i < size; i++) { \
            elements[i] = current->value; \
            current = current->next; \
        } \
        return elements; \
    }

// Define List for int type
DEFINE_LIST(int)

int main() {
    char* s[] = {"foo", "bar", "zoo"};
    int size = sizeof(s) / sizeof(s[0]);

    // Using the generic SlicesIndex function
    int index = SlicesIndex(char*, s, size, "zoo");
    printf("index of zoo: %d\n", index);

    // Using the generic List
    List_int list = {NULL, NULL};
    Push_int(&list, 10);
    Push_int(&list, 13);
    Push_int(&list, 23);

    int* elements = AllElements_int(&list);
    printf("list: ");
    for (int i = 0; i < 3; i++) {
        printf("%d ", elements[i]);
    }
    printf("\n");

    free(elements);
    return 0;
}

In this C implementation, we’ve used preprocessor macros to simulate generics. The SlicesIndex macro creates a generic function to find the index of an element in an array. The DEFINE_LIST macro defines a generic linked list structure and its associated functions.

To compile and run the program:

$ gcc -o generics generics.c
$ ./generics
index of zoo: 2
list: 10 13 23

This example demonstrates how to implement generic-like functionality in C using macros. While C doesn’t have built-in support for generics like some modern languages, this approach allows for type-agnostic code reuse.

Note that this implementation has limitations and doesn’t provide true type safety at compile-time. In practice, more robust solutions might involve code generation or careful use of void pointers, depending on the specific requirements of the project.