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)