gpt4 book ai didi

c++ - 通过 C++ 中的模板包重新创建函数签名和调用

转载 作者:搜寻专家 更新时间:2023-10-31 01:27:02 24 4
gpt4 key购买 nike

我想用 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 创建一个由函数指针和签名指定的可调用对象,因为参数是相同类型的 int 只需要参数数量的计数参数。当我调用 一个函数时,我指定了函数对象的索引和一个堆栈。实际的 c 调用通过参数计数和类型转换进行解码,调用参数从堆栈中获取。

如何在 C++ 中将 addfunccall 函数重写为模板对象?我如何使用模板包来计算给定函数的参数数量并重新生成对函数的调用?如何摆脱 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com