c++ - 在 C++ 中重新创建函数签名并通过模板包进行调用

标签 c++ templates

我有 C 代码,想用 C++ 重写。 C 代码是解释器的一部分,其中函数是用 C 定义的,但实际调用来自解释源。基本上它的作用如下所示:

#include <vector>

void f1(int a0) { }
void f2(int a0,int a1) { }
void f3(int a0,int a1,int a2) { }
void f4(int a0,int a1,int a2,int a3) { }

struct m {
    void *p;
    int c;
};

std::vector<m> ma;

int addfunc(void *p, int c) {
    int i = ma.size();
    ma.push_back({p,c});
    return i;
}

void call(int idx, int *stack) {
    switch (ma[idx].c) {
    case 1:
    ((void (*)(int))ma[idx].p)  (stack[0]);
    break;
    case 2:
    ((void (*)(int,int))ma[idx].p)  (stack[0],stack[1]);
    break;
    case 3:
    ((void (*)(int,int,int))ma[idx].p)  (stack[0],stack[1],stack[2]);
    break;
    case 4:
    ((void (*)(int,int,int,int))ma[idx].p)  (stack[0],stack[1],stack[2],stack[3]);
    break;
    }
}

int main (void) {
    int stack[5] = { 0,1,2,3,4 };
    /* define */
    int i1 = addfunc((void*)f1, 1);
    int i2 = addfunc((void*)f2, 2);
    int i3 = addfunc((void*)f3, 3);
    int i4 = addfunc((void*)f4, 4);
    /* call */
    call(i1,stack);
    call(i2,stack);
    call(i3,stack);
    call(i4,stack);
}

addfunc 创建一个由函数指针和签名指定的可调用对象,因为参数的类型相同,只需要一个 count 参数来表示参数的数量。 当我调用函数时,我指定函数对象的索引和堆栈。实际的 c 调用通过参数计数进行解码并进行类型转换,调用参数从堆栈中获取。

如何将 addfunccall 函数重写为 C++ 中的模板对象?如何使用模板包来计算给定函数的参数数量并重新生成对该函数的调用? 如何摆脱 switch 语句和函数指针类型转换?我看到了luawrapperBinder 类执行类似的操作。不过代码相当复杂。就我而言,参数都是同一类型。 最后我想做一些类似的事情(伪代码):

vector<meth> ma;
...
int i0 = addfunc([](int a) { });
int i1 = addfunc([](int a,int b) { });
int i2 = addfunc([](int a,int b,int b) { });
int i3 = addfunc([](int a,int b,int c,int c) { });
...
ma[i0](stack);
ma[i1](stack);
ma[i2](stack);
ma[i3](stack);

最佳答案

好吧,如果它们只是 C 函数,为什么不在函数指针类型上重载呢?

std::function<void(std::array<int, 5>)> addfunc(void (*f)(int)) {
    return [f](std::array<int, 5> const& a) { f(a[0]); };
}

std::function<void(std::array<int, 5>)> addfunc(void (*f)(int,int)) {
    return [f](std::array<int, 5> const& a) { f(a[0], a[1]); };
}

// repeat for all necessary arities

然后创建std::vector<std::function<void(std::array<int, 5>)>>并推迟你的所有功能。它很简单,不需要任何模板并且工作得相当好。它引入了std::function的开销不过。

您可以通过引入您自己的可调用类型(其中n个)来摆脱它,这将对应于上面的重载,提供 operator()并在里面存储适当的函数类型。

Live example .

关于c++ - 在 C++ 中重新创建函数签名并通过模板包进行调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54188397/

相关文章:

c++ - 模板特化中 T[N] 和 T[] 的区别?

c++ - 如何使读取功能不挂起?

templates - 使用 require.js、主干和下划线本地化模板

c++ - `apply` 模板在 g++ 中编译但在 clang++ 和 vc++ 中不编译

c++ - 模板代理方法无法编译

c++ - 将 std::pair<T1, T2> const 转换为 std::pair<T1 const, T2> const 安全吗?

C++链表中的访问冲突读取位置

c++ - 使用c或c++解码红外遥控代码

c++ - 正常 block 后检测到堆损坏

c++ - 如何从 C++ 模板中解压 std::tuple?