Reputation: 60
I need to write the implementation of a function that accept as parameters:
The function prototype should be something like this :
void caller_imp( generic_function_pointer, varargs_list )
Suppose you have the following code example:
#define caller(function, ...) caller_imp(function, __VA_ARGS__)
int test (int a)
{
return a;
}
int test2(int a, int b)
{
return a+b;
}
void caller_imp(???,???)
{
???
}
int main(int argc, char **argv)
{
caller(test,33);
caller(test2,44,55);
return 0;
}
Of consequence im in need to write the proper implementation of the "caller_imp" function.
UPDATED DETAILS :
int test (int a)
int test2(int a, int b)
are only an example, the function pointer and the parameters coul be varying, for example :
int test3(int a,char *str)
should be considered valid
unfortunatly I dont know which function pointer will be called or the number of the parameters or their type.
In C++ I think I could do :
template<typename Function, typename... Params>
auto call_imp(Function function, Params... params)
->typename std::enable_if<std::is_same<void,decltype(function(params...))>::value,decltype(function(params...))>::type
{
function(std::forward<Params>(params)...);
}
Thanks in advance.
Upvotes: 0
Views: 168
Reputation: 222669
This is not supported in the C standard because there is no information available about what parameters a function expects. That is, given a function pointer alone, we cannot know whether the function expects one int
argument, two int
arguments, one int
and one char *
argument, or something else. Therefore, even if we had a way to dynamically construct an argument list, we would not know which argument list to construct.
If you do know which function requires which arguments, you can write specific code for each case:
#include <stdarg.h>
void caller_imp(void (*f)(void),...)
{
va_list ap;
va_start(ap, f);
if (f == (void (*)(void)) test)
{
int a = va_arg(ap, int);
((int (*)(int)) f)(a);
}
else if (f == (void (*)(void)) test2)
{
int a = va_arg(ap, int);
int b = va_arg(ap, int);
((int (*)(int, int)) f)(a, b);
}
va_end(ap);
}
Then the caller
macro should convert the function pointer:
#define caller(function, ...) caller_imp((void (*)(void))(function), __VA_ARGS__)
If you do not know which function requires which arguments, it would be necessary to provide this information in some way, such as creating an enumeration of function types and requiring the caller to provide it.
Upvotes: 2
Reputation: 213810
You can do this to allow either 1 or 2 arguments of type int
:
#define COUNT_ARGS(...) ( sizeof (int[]){__VA_ARGS__} / sizeof(int) )
#define caller(function, ...) (COUNT_ARGS(__VA_ARGS__) == 1 ? function : function##2) (__VA_ARGS__)
Usage:
caller(test, 1);
caller(test, 1, 2);
Please note that error handling is pretty non-existent here though...
Upvotes: 1