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...
If the expression parameter is a call to a function or an overloaded operator function, decltype(expression) is the return type of the function. Parentheses around an overloaded operator are ignored. If the expression parameter is an rvalue, decltype(expression) is the type of expression.
Decltype keyword in C++ Decltype stands for declared type of an entity or the type of an expression. It lets you extract the type from the variable so decltype is sort of an operator that evaluates the type of passed expression. SYNTAX : decltype( expression )
The documentation states that it is "useful primarily to developers who write template libraries." decltype was added to the mainline of the GCC C++ compiler in version 4.3, released on March 5, 2008.
decltype is a compile time evaluation (like sizeof ), and so can only use the static type.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With