In my C project, there is a struct, created by another colleague, containing some function pointers:
struct tools {
int (*tool_a) (int, int, int);
...
};
I have no right to change this struct and relative files.
Now I'm coding with the struct.
I have to define a function, whose return type and list of arguments must be the same with the tools.tool_a
.
Meaning that my function must be as below:
int my_func(int, int, int);
The problem is that the struct changes a lot, especially the return types, for example int
is replaced by size_t
today, so I have to change my code a lot.
I know that decltype
in C++ can help me so I just want to know if C has something equivalent?
I'm thinking I may use macro but I don't know how, I even don't know if it's possible or not.
I'm developing some testing tools for linux-kernel with C.
There have been many versions of custom kernels coming from other groups in my company. For historical reasons, some of them used int
, others used size_t
or ssize_t
and so on.
Now when I code, I have to do like this:
// int my_func(int a, int b, int c)
size_t my_func(int a, int b, int c)
// ssize_t my_func(int a, int b, int c)
{}
struct tools my_tool = {
.tool_a = my_func;
}
I have to keep commenting and uncommenting...
The sane solution is to enforce a typedef
. If that isn't possible, and the number of alternative types the function could have are limited, as seems to be the case, you could cook up something with C11 _Generic
.
Instead of having a single function called my_func
, create multiple functions with different names. Prefix their names depending on the return type. Then have a macro which in turn re-directs to the appropriate function, based on the type passed.
Example:
#include <stdio.h>
/*** the struct that cannot be changed ***/
struct tools {
int (*tool_a) (int, int, int);
};
/*** any number of functions with different types ***/
int int_my_func(int a, int b, int c)
{
puts(__func__);
}
size_t size_t_my_func(int a, int b, int c)
{
puts(__func__);
}
/*** macro to select the appropriate function based on type ***/
#define my_func_typeof(type) \
_Generic( (type), \
int(*)(int,int,int) : int_my_func, \
size_t(*)(int,int,int) : size_t_my_func)
/*** caller code ***/
int main (void)
{
struct tools my_tool = {
.tool_a = my_func_typeof( (struct tools){0}.tool_a )
};
my_tool.tool_a(1,2,3);
}
Here I used a compound literal (struct tools){0}.tool_a
to create a dummy object of the same type as tool_a
, then passed that on to the macro which picks the appropriate function. If the type is not supported, there will be a compiler error since no matching _Generic association could be found.