【问题标题】:Making a regular function wrap a member function with templates使常规函数用模板包装成员函数
【发布时间】:2017-06-11 16:18:29
【问题描述】:

我正在使用一个具有 C API 的框架,其 typedef 看起来像这样:

typedef int (*function_type)(int argc, voidptr_t args[], void *data)

还有一个采用如下函数指针的函数:

void create_callback(function_type fn, void *data);

(如果不明显,voidptr_t 只是 void * 的另一个 typedef)

框架将根据需要在特定时间调用回调,并设置 argc 和 args 参数以反映当时有效的条件。 argc 永远不会小于 1,并且 args 中的第一个条目将始终是指向一些有效数据的指针,这些数据可以转换为指向我程序中某个类的指针,并且在许多方面可以被认为是“this”指针,因为它指示回调预期作用或使用的对象或数据。

我将从 C++ 调用此 API,并且我想要一种方法来包装类的成员函数,如下所示:

class A
{
    int member_fn1(int argc, voidptr_t args[], void *data);
};

class B
{
    int member_fn2(int argc, voidptr_t args[], void *data);
};

现在我想要一种将这些成员函数用作回调的方法......我可以通过更改 A 和 B 的定义来包含我可以用作回调的静态函数,如下所示:

class A
{
    int member_fn1(int argc, voidptr_t args[], void *data);
    static int call_fn1(int argc, voidptr_t args[], void *data)
    {
       ((A*)args[0])->*fn1(argc-1,&args[1],dat
    }
};

class B
{
    int member_fn2(int argc, voidptr_t args[], void *data);
    static int call_fn2(int argc, voidptr_t args[], void *data)
    {
       ((B*)args[0])->fn2(argc-1,&args[1],data);
    }
};

但是,如果我必须为要用作回调的每个成员函数定义一个附加的此类静态函数,这将变得非常乏味。然而,正如您所见,这个想法是只将其他参数传递给成员函数,并允许第一个参数假定 this 的值。

我想要做的是定义某种模板函数,我可以将它作为参数传递给create_callback,并将包装一个成员函数,以便可以作为回调调用它。

wrap_function 看起来像这样:

template<????> int wrap_function(int argc, voidptr_t args[], void *data)
{
   try {
      return ((X*)args[0])->fn(argc-1, &args[1], data);
   } catch(...) {
      // handle any exception safely, because we can't let it get back into C code
      handle_exception(std::current_exception());
      return -1
   }
}

其中X 是类的类型名,fn 是成员函数本身。

请注意,此函数还可以灵活地处理异常,否则我会为我想用作回调的每个成员函数一遍又一遍地编写几乎相同的代码......这就是为什么我想将它设置为模板函数。

所以一旦我定义了wrap_function,我就可以通过这样做在 API 中定义回调:

create_callback(wrap_function<&A::member_function1>, some_data)
create_callback(wrap_function<&B::member_function2>, some_other_data)

由于wrap_function 的定义只是一个常规函数而不是方法,我可以将其地址作为常规函数指针传递给C API,该函数的职责是将其工作委托给正确的正确类中的成员函数。

但是我该如何定义wrap_function 模板,以使其正常工作?

真诚地希望这个问题是清楚的......如果有人觉得它需要更好地描述,请在评论中具体指出下面的不明确之处,以便我可以改进这个问题。

【问题讨论】:

    标签: c++ c++11 templates member-function-pointers


    【解决方案1】:
    template <typename X, int (X::*fn)(int, voidptr_t[], void*)>
    int wrap_function(int argc, voidptr_t args[], void *data) {
      return (static_cast<X*>(args[0])->*fn)(argc-1, &args[1], data);
    }
    

    我认为应该可以。你这样使用它:

    create_callback(wrap_function<A, &A::member_function1>, some_data)
    

    【讨论】:

    • wrap_function 当然必须是static 成员。
    • @aschepler 到底属于哪一类?我将其设想为一个独立的非成员函数模板。
    • 哎呀,是的。我错过了这里涉及多个课程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-02
    相关资源
    最近更新 更多