使用 varargs 参数的 C++ 泛型函数调用

2023-12-05

在我的项目中,我有具有不同数量、不同类型的输入参数的函数。由于这些函数是库的一部分,因此我无法更改它们的定义或主体。

void methodA(boolean p1, int p2, long p3){
    ... some unrelevant code here ...
}

void methodB(int p1, int p2, int p3, long p4){
    ... some unrelevant code here too ...
}

int methodC(long p4){
    ...
}

在我的项目中,我需要一个方法,它将接收这些函数之一的地址。此外,它还接收格式正确的参数列表(适合第一个参数中的函数)。然后这个方法必须使用传递的参数调用传递的函数。

这是我现在所拥有的:(我稍微简化了代码以使我的想法清晰)

void intercaller(void* some_func_address, ...){

    // VARARGS parameters extractor
    va_list listPointer;
    va_start( listPointer, some_func_address );

    int p1 = va_arg( listPointer, int );
    int p2 = va_arg( listPointer, int );
    int p3 = va_arg( listPointer, int );
    long p4 = va_arg( listPointer, long );

    // TODO: THIS IS NOT GENERIC CALL , CANN ONLY CALL METHOD B
    ((void (*)( int , int , int , long )) some_func_address)( p1 , p2 , p3 , p4 );

    va_end( listPointer );
}

我的问题是实际的函数调用。函数调用中的参数列表应该是通用的,并且应该能够包含不同数量的参数,遗憾的是我不知道该怎么做...我尝试过传递可变参数列表,如下所示:

((void (*)( va_list )) some_func_address)( listPointer);

但这会弄乱被调用函数中的参数......

所以我的问题是:有没有办法以通用方式调用具有给定参数的给定函数?也许我需要某种 typedeff 或包装函数?


如果你没有std::invoke然而,使用可变参数模板。治疗void功能很好,使用SFINAE.

template<typename R, typename... Args>
auto call(R(*function)(Args...), Args... args) -> typename std::enable_if<!std::is_same<R, void>::value, R>::type {
    return function(args...);
}

template<typename... Args>
void call(void (*function)(Args...), Args... args) {
    function(args...);
}

Example:

void a() {
    std::cout << 'a';
}

void b(int a) {
    std::cout << "b:" << a;
}

int c(int a) {
    return a;
}

int main() {
    call(a);
    call(b, 1);
    std::cout << "c:" << call(c, 2);
}

别忘了#include <type_traits> for std::enable_if and std::is_same.

在线尝试一下!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 varargs 参数的 C++ 泛型函数调用 的相关文章

随机推荐