回调未知的类+函数

Callback an unknown class+function

本文关键字:函数 未知 回调      更新时间:2023-10-16

我的C++已经生锈了。我希望MyClass对Foo一无所知,并有一个回调来运行Foo中的函数。我不知道如何定义callback_pair或如何调用SetCallback

class MyClass{
    tuple<cb, ptr> callback_pair
    int run() { 
        auto that=callback_pair<1>();
        auto cb = callback_pair<0>(); 
        int a=1, b=2, c=3;
        auto result = cb(that, a, b, c); //this calls foo.the_function
        return result;
    }
    void SetCallback(tuple<cb, ptr> cb) { callback_pair=cb; )
};
class Foo {
    int d;
    int the_func(int a, b, c) {
        return a+b+c+d
    }
}
//myclass.SetCallback(what_do_I_write_here)

好吧,MyClass必须知道关于Foo的一些,即您计划用作回调的任何方法的签名;否则,它怎么知道什么作为参数传入,或者期望得到什么类型的输出?如果回调签名是已知的并且是固定的,例如上面的int(int,int,int),那么可以使用这样的构造:

class MyClass {
    std::function<int(int,int,int)> callback;
public:
    int run() {
        return callback(1,2,3); // or whatever
    }
    template <typename Class>
    void SetCallback (Class& o, int (Class::*m) (int,int,int)) {
        callback = [&o,m] (int a, int b, int c) { return (o.*m)(a,b,c); };
    }
    template <typename Class>
    void SetCallback (Class const& o, int (Class::*m) (int,int,int) const) {
        callback = [&o,m] (int a, int b, int c) { return (o.*m)(a,b,c); };
    }
};

MyClass的上述实现如下:callback是一个函数对象,最初未定义,它占用三个int,并返回一个intSetCallback采用两个参数:应该对其执行回调的对象o和符合callback签名的该对象上的方法m。它不在乎o的类型是什么;由于类型擦除,MyClass永远不需要知道它实际在调用什么。

请特别注意SetCallback的两个版本——分别用于const和非const对象。实际上,您也应该为volatileconst volatile编写重载,但这些重载比const要少得多。在未来,一旦异常规范和事务成为类型系统的一部分,我们还必须关心noexcept和同步,如果没有一些非常聪明的语言支持,由此产生的类型组合爆炸将很难有效处理。但这个例子向您展示了这类代码是如何编写的,对于您的目的来说,它可能已经足够好了。

实现看起来很难看,但实际上它提供了一个非常干净的接口;给定如上所述的Foo,您将使用MyClass的回调功能,如下所示:

MyClass test;
Foo foo;
foo.d = 4;
test.SetCallback (foo, &Foo::the_func);
int result = test.run(); // result = 10

上面的代码将适用于任何具有签名为int(int,int,int)的方法的类型。请注意,在调用run之前,必须先调用SetCallback,否则会出现std::bad_function_call异常,因为回调尚未定义。