首页 > 解决方案 > 带有可变参数的泛型函数的 C 实现

问题描述

我需要编写一个接受作为参数的函数的实现:

函数原型应该是这样的:

void caller_imp( generic_function_pointer, varargs_list )

假设您有以下代码示例:

#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;
}

结果,我需要编写“caller_imp”函数的正确实现。

更新详情:

int test (int a)
int test2(int a, int b)

只是一个例子,函数指针和参数可以变化,例如:

int test3(int a,char *str)

应该被认为是有效的

不幸的是,我不知道将调用哪个函数指针或参数的数量或它们的类型。

在 C++ 中,我想我可以这样做:

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)...);
}

提前致谢。

标签: c

解决方案


这在 C 标准中不受支持,因为没有关于函数需要哪些参数的信息。也就是说,仅给定一个函数指针,我们无法知道该函数是否需要一个int参数、两个int参数、一个int和一个char *参数,或者其他什么。因此,即使我们有办法动态构造参数列表,我们也不知道要构造哪个参数列表。

如果您确实知道哪个函数需要哪个参数,则可以为每种情况编写特定的代码:

#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);
}

然后caller宏应该转换函数指针:

#define caller(function, ...) caller_imp((void (*)(void))(function), __VA_ARGS__)

如果您不知道哪个函数需要哪些参数,则有必要以某种方式提供此信息,例如创建函数类型的枚举并要求调用者提供它。


推荐阅读