C++成员函数的多个非静态回调

问题描述 投票:0回答:1

我发现使用下面链接的答案中的代码效果很好,但在我的用例中存在问题。它有效地为非静态成员函数创建了一个“静态包装器”,以作为回调传递。

#include <stdio.h>
#include <functional>

template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
   template <typename... Args>
   static Ret callback(Args... args) {
      return func(args...);
   }
   static std::function<Ret(Params...)> func;
};
template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;

所以我在头文件中包含了这一点,然后各种类都有如下代码。问题是,当尝试在同一范围内定义两个这样的回调时,第二个会覆盖第一个。

typedef int (*callback_t)(int*,int*);

Callback<int(int*,int*)>::func = std::bind(&myClass::myMethod1, this, std::placeholders::_1, std::placeholders::_2);
callback_t func1 = static_cast<callback_t>(Callback<int(int*,int*)>::callback);      
register_task1_with_library(func1);

Callback<int(int*,int*)>::func = std::bind(&myClass::myMethod2, this, std::placeholders::_1, std::placeholders::_2);
callback_t func2 = static_cast<callback_t>(Callback<int(int*,int*)>::callback);      
register_task2_with_library(func2);

第一个注册的回调被重定向到第二个。 为此创建第二个“静态包装器”的最小更改是什么?似乎必须复制头文件的全部内容,用 Callback2 之类的内容替换 Callback,才能有第二个“静态包装器”可用.

还有一个更简单的示例可以显示相同的问题:

#include <iostream>
#include "callback.hpp"
void print1(std::string msg)
{
    std::cout << "print1:\t" << msg << std::endl;
}
void print2(std::string msg)
{
    std::cout << "print2:\t\t" << msg << std::endl;
}
int main(int argc, char ** argv)
{
    typedef void (*callback_t)(std::string);
    Callback<void(std::string)>::func = std::bind(print1, std::placeholders::_1);
    callback_t func1 = static_cast<callback_t>(Callback<void(std::string)>::callback);

    Callback<void(std::string)>::func = std::bind(print2, std::placeholders::_1);
    callback_t func2 = static_cast<callback_t>(Callback<void(std::string)>::callback);

    func1("howdy");
    func2("partner");
    return 0;
}

相关项目:https://stackoverflow.com/a/29817048/2725742使用c++类成员函数作为c回调函数,线程安全版本

修改后的模板如下是我在评论讨论后最终得到的,我的测试表明它在我的用例中很好。添加的“标签”参数有助于保持每个项目的唯一性。

template <typename T, int tag = 0>
struct Callback;
template <typename Ret, typename... Params, int tag>
struct Callback<Ret(Params...), tag> {
   template <typename... Args>
   static Ret callback(Args... args) {
      return func(args...);
   }
   int m_tag = tag;
   static std::function<Ret(Params...)> func;
};
template <typename Ret, typename... Params, int tag>
std::function<Ret(Params...)> Callback<Ret(Params...), tag>::func;
c++ c++11 templates callback asynccallback
1个回答
0
投票

使用更新的静态包装模板(包括唯一标签),一些有关如何使用它的示例:

对于像

int myClass::mult(int a, int b)
这样的回调成员函数:

const int uniqueTag = 1234;
typedef int(*intCallback_t)(int, int);
Callback<int(int, int), uniqueTag>::func = std::bind(&myClass::mult, this, std::placeholders::_1, std::placeholders::_2);
intCallback_t intFunc = static_cast<intCallback_t>(Callback<int(int, int), uniqueTag>::callback);

或者对于像

void myClass::callback()
这样的回调成员函数:

const int uniqueTag = 4321;
typedef void(*callback_t)();
Callback<void(), uniqueTag>::func = std::bind(&myClass::callback, this);
callback_tintFunc = static_cast<callback_t>(Callback<void(), uniqueTag>::callback);
© www.soinside.com 2019 - 2024. All rights reserved.