I need to implement some methods that do stuff with different kinds of number arrays. Usually, I'd use generics for that job, but as C doesn't provide them, I'm now trying to emulate them using macros.

Here's an example of what I'm trying to do:

#ifndef TYPE
#define TYPE int
#endif

TYPE get_minimum_##TYPE (TYPE * nums, int len){
    TYPE min = nums[0];

    for (int i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}

However, this won't compile. The clang error message:

error: expected ';' after top level declarator

Is there any way to do this in C? Or do I need implement this for every type by hand?


Solution 1:

You can do something like this in a header file:

//
// generic.h
//

#define TOKENPASTE(x, y) x ## y

#define GET_MINIMUM(T) TOKENPASTE(get_minimum_, T)

TYPE GET_MINIMUM (TYPE) (TYPE * nums, size_t len){
    TYPE min = nums[0];

    for (size_t i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}

and then #include it in a source file for each required type, e.g.:

//
// generic.c
//

#define TYPE int
#include "generic.h"
#undef TYPE

#define TYPE float
#include "generic.h"
#undef TYPE

You can test this by running it through the preprocessor:

$ gcc -E generic.c 

int get_minimum_int (int * nums, size_t len){
    int min = nums[0];

    for (size_t i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}

float get_minimum_float (float * nums, size_t len){
    float min = nums[0];

    for (size_t i = 1; i < len; i++) {
        if (nums[i] < min) {
            min = nums[i];
        }
    }

    return min;
}

Solution 2:

Actually, the best you can do is to define a macro that will generate the function for the given type.

#define define_get_minimum(T) \
T get_minimum_##T(T* nums, int len){ \
    T min = nums[0]; \
    for (int i = 1; i < len; i++) { \
        if (nums[i] < min) { \
            min = nums[i]; \
        } \
    } \
    return min; \
}

Then, you can call that macro to define the specializations you need (with C++ template, a similar thing is done automagically by the compiler).

define_get_minimum(int)
define_get_minimum(double)
define_get_minimum(float)

Another thing that a C++ compiler does automagically is deduce the overloaded function you need. You can't have that in C, so you will have to tell you are using the it specialization. You can simulate a template-like syntax for your function with the following macro (the C++ <> are just replaced by ()):

#define get_minimum(T) get_minimum_##T

Then, you should be able to call it the following way:

int main()
{
    // Define arr as char* array...
    // Do stuff...
    int res = get_minimum(int)(arr, 3);
}

I did not test this code, but it should work.