Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C equivalent to C++ decltype

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.

REAL CASE

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...

like image 691
Yves Avatar asked Jan 10 '18 07:01

Yves


People also ask

What is the decltype of a function?

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.

What does decltype stand for?

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 )

When did C++ add decltype?

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.

Is decltype runtime or compile time?

decltype is a compile time evaluation (like sizeof ), and so can only use the static type.


1 Answers

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.

like image 151
Lundin Avatar answered Oct 26 '22 20:10

Lundin