Home > OS >  How to have a function pointer type that takes an arbitrary pointer as argument?
How to have a function pointer type that takes an arbitrary pointer as argument?

Time:10-04

I have a function that applies a function of type apply_fn to each element of a list, and a macro that will declare a temporary function an pass it to list_apply:

typedef void apply_fn( void * );

void list_apply( t_list *lst, apply_fn *apply );

# define list_apply( lst, apply_fn_body ) \
  do {\
    void _l_function_ apply_fn_body\
    list_apply(lst, _l_function_);\
  while (0)

I use this macro to simulate an anonymous function (like in js) so I can call my function like this for example:

list_apply(&my_list, (void * elem) {
  // do something with the element
});

So everything works fine until this point (with gcc), but I want to be able to call my function like this for example:

list_apply(&my_list, (int * elem) {
  // do something with element as an integer
});

I know that I can define my function type like this:

typedef void apply_fn();

And it works fine then but if for example I do this:

list_apply(&my_list, ( void ) {
  // function that takes no parameter instead of one pointer
});

I want it to still throw a compilation error instead of undefined behavior, what I'd like to be able to do is:

typedef void apply_fn( any_type * );

That's of course not possible but are there some alternatives that would do the same ?

CodePudding user response:

I found a way to do that:

First instead of typedef void apply_fn( void * ); I wrote typedef void apply_fn();.

Then to throw an error if parameters are invalid I had to add an argument to my macro: I pass the type that we want to it and I cast the nested function to a function pointer which has the right type and number of arguments like this:

# define list_apply( lst, type, apply_fn_body ) \
  do {\
    void _l_function_ apply_fn_body\
    void (*_checker_)( type * ptr ) = _l_function_;\
    list_apply(&lst, _l_function_);\
  } while (0)

CodePudding user response:

I assume that this solution is limited only to GCC world.

You need two nested functions. One that processes any_type* and a wrapper that maps it from void*. Finally, pass the wrapper to list_apply().

You need something that expands this code:

list_apply(&my_list, (int * elem) { *elem = 42; });

to this:

do {
    void _l_function_(int * elem) { *elem = 42; }
    void _l_wrapper_(void* elem) { _l_function_(elem); }
    list_apply(lst, _l_wrapper_);
}  while (0)

The possible macro could be:

# define list_apply( lst, type, apply_fn_body )          \
  do {                                                   \
    void _l_function_ apply_fn_body                      \
    void _l_wrapper_(void* elem) { _l_function_(elem); } \
    list_apply(&lst, _l_wrapper_);                       \
  } while (0)
  • Related