Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何向函数指针数组中的每个函数添加标准例程? 我在C++中为嵌入式系统创建了一个应用程序。因此,我被一些C库束缚住了,没有自由使用大量std功能_C++_Arrays_Templates_Function Pointers - Fatal编程技术网

如何向函数指针数组中的每个函数添加标准例程? 我在C++中为嵌入式系统创建了一个应用程序。因此,我被一些C库束缚住了,没有自由使用大量std功能

如何向函数指针数组中的每个函数添加标准例程? 我在C++中为嵌入式系统创建了一个应用程序。因此,我被一些C库束缚住了,没有自由使用大量std功能,c++,arrays,templates,function-pointers,C++,Arrays,Templates,Function Pointers,我有一个回调签名: typedef int (*callback_fn)(int a, int b); 包含指向已注册回调的指针的列表: callback_fn my_callback_functions[10]; 以及一个将回调添加到此列表的函数: void add_callback(int function_iterator, callback_fn fn) { my_callback_functions[function_iterator] = fn; } 然后回调被传递到这

我有一个回调签名:

typedef int (*callback_fn)(int a, int b);
包含指向已注册回调的指针的列表:

callback_fn my_callback_functions[10];
以及一个将回调添加到此列表的函数:

void add_callback(int function_iterator, callback_fn fn)
{
    my_callback_functions[function_iterator] = fn;
}
然后回调被传递到这个库,它在一些事件上调用回调

现在,我想为每个回调添加一个小例程,以便每次调用时都可以重置计时器:

myTimer.reset();
如何在不更改签名或远离函数指针(我需要与库交互)的情况下将其添加到每个调用中


我尝试了一些使用模板的方法,但找不到正确的方法来实现这一点。

定义一个包含静态函数的结构。这将是您的回调之一。结构的名称并不重要,只是函数本身的名称必须是常量。例如:

struct MyCallback1 {
  static int callback(int a, int b) {
     //..
  }
};
现在我们可以编写包装器:

template<typename T>
int decorated_callback(int a, int b) {
   myTimer.reset();
   return T::callback(a, b);
}
模板
int-u回调(int-a,int-b){
myTimer.reset();
返回T::回调(a,b);
}
并将其注册为回调:

add_callback(0, &decorated_callback<MyCallback1>);
add_回调(0,&u回调);

让我们从天真开始,然后再添加复杂

添加例程的最简单方法是编辑回调函数。也就是说,如果其中一个回调是
fun1()
,则可以添加行
myTimer.reset()到函数体的开头

除了。。。也许不是每次调用此函数都应该重置计时器(不要忘记考虑将来的更改)。我们可以不那么天真,创建一个包装函数,重置计时器,然后调用
fun1()
。回调可以调用此包装器,而其他调用使用原始函数

int wrap1(int a, int b)
{
    myTimer.reset();
    return fun1(a, b);
}
除了。。。我很懒。我不想为每个回调都编写包装器。我会把这个任务交给其他人,一个不会抱怨我懒惰的人,一个像
gcc
(或者你选择的任何编译器)这样的人。我宁愿编写一个模板来展示如何编写这个包装器,然后让编译器根据需要生成包装器。唯一不同的是回调函数,因此它成为模板参数

template <callback_fn F>
int wrap(int a, int b)
{
    myTimer.reset();
    return F(a, b);
}
模板
整数换行(整数a,整数b)
{
myTimer.reset();
返回F(a,b);
}
现在,您可以使用如下行添加回调

    add_callback(0, wrap<fun1>);
    add_callback(1, wrap<fun2>);
    add_callback<fun1>(0);
    add_callback<fun2>(1);
add_回调(0,wrap);
添加_回调(1,换行);

这可以推广到处理指针类型,而不是
回调\u fn
,但我将暂缓设计一个解决方案。如果有人需要更复杂的知识,他总是可以提出一个新的问题来引用这个问题。

我想到了另一种方法。在中,添加了不更改呼叫站点的限制。这让我思考为什么有人会施加这样的限制。一个潜在的动机是减少
add\u callback()
调用方的心理负担。如果调用方不必记住包装它们的函数,那么它将更加健壮。如果插入的代码是为了调试,这不是一个大问题。然而,如果插入的代码是用于生产的——可能是性能监控的一部分——如果有人忘记了包装器,那将是一件大事。所以我开始思考编译器可以如何帮助我

一般来说,使事情自动化是一个合理的目标。程序员需要记住的越少,出错的机会就越少。即使OP的动机是不同的,我提出这种方法为未来读者考虑。

除了包装器函数模板外,还可以将
add\u callback()
更改为函数模板。与其将所需函数作为函数参数传递,不如将其作为模板参数传递。
警告:这意味着必须在编译时知道回调函数;像
条件这样的表达式?fun1:fun2
需要扩展为一个完整的
if
语句

此方法的第一部分与我之前的方法相同。创建包装器函数模板

// (Could be private if there was a class encompassing this functionality.)
template <callback_fn F>
int wrap(int a, int b)
{
    myTimer.reset();
    return F(a, b);
}
最后,更改呼叫站点。现有调用看起来像
add\u callback(0,fun1)
,现在编译器将拒绝该调用。没有错过电话的危险。添加回调的新语法如下所示

    add_callback(0, wrap<fun1>);
    add_callback(1, wrap<fun2>);
    add_callback<fun1>(0);
    add_callback<fun2>(1);
add_回调(0);
添加_回调(1);

@RemyLebeau恐怕我听不懂你的话。正如我理解的那样,OP在代码中定义了各种回调函数,然后在库中注册这些函数。上述设计要求他要么将这些自由函数重命名为静态方法,要么将它们包装为某种静态方法。我假设
my_callback\u functions
是OP无法直接访问的第三方库的一个实现细节。在我听来,OP好像接到了其他人的回电,然后打电话给他们。但是,如果OP是定义回调的OP,那么是的,您的方法可以处理得很好。现在您已经有了一些使用模板的答案,您可能想回顾一下您的尝试,看看它们失败的原因。如果你自己不明白原因,那么这里的另一个问题可能是合理的。谢谢你的回答!我的问题似乎不是很清楚,如果你愿意,请查看更新。@Micha在收到答案后大幅更改问题是不礼貌的。若你们发现你们并没有问你们认为你们问了什么,你们应该(考虑接受一个答案)问一个新的问题,并有新的限制。@JaMiTI当然并没有粗鲁的意思。从界面的角度来看,很明显我的澄清就是我一开始所要求的。显然我