Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pseudo-generics in C

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?

like image 225
fb55 Avatar asked May 13 '13 12:05

fb55


People also ask

Is there generics in C?

Generics are syntax components of a programming language that can be reused for different types of objects. Typically, generics take the form classes or functions, which take type(s) as a parameter.

What is generic type in C?

Generics is the idea to allow type (Integer, String, … etc and user-defined types) to be a parameter to methods, classes and interfaces. For example, classes like an array, map, etc, which can be used using generics very efficiently.

What is Genericity in oops?

Genericity is one of the most powerful means for obtaining flexibility in programming with statically typed programming languages. Genericity constructs take on very different forms, the choice of which has a considerable impact on expressiveness, modularity, static checkability and efficiency properties of programs.

Do templates exist in C?

C does not have static templates, but you can use macros to emulate them.


2 Answers

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; } 
like image 176
Paul R Avatar answered Sep 19 '22 14:09

Paul R


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.

like image 24
Jehan Avatar answered Sep 17 '22 14:09

Jehan