【发布时间】:2016-06-25 13:06:13
【问题描述】:
我想注册回调函数,并将它们存储在一个向量中以调用它们。还应该允许使用成员函数作为回调函数。
我最初的方法是通过以下方式使用<functional>:
#include <functional>
#include <vector>
#include <iostream>
std::vector<std::function<void()>> functions;
struct Foo {
void Bar() {
std::cout << "Hello" << std::endl;
}
};
template<class T>
void Register( T* obj, std::function<void(T*)> function ) {
functions.push_back( std::bind( function, obj ) );
}
void main(){
Foo foo;
Register(&foo, &Foo::Bar);
}
这不起作用,因为编译器无法推断参数类型。只有当我明确指定类型时它才有效:Register<Foo>(&foo, &Foo::Bar);。这不是我想要的,所以我尝试使用旧的函数指针:
template<class T>
void Register( T* obj, void(T::* function)() ) {
functions.push_back( std::bind( function, obj ) );
}
它奏效了。由于我不喜欢这种形式的函数指针,所以我为 Memberfunction 指针创建了一个类型:
template<class Owner>
using Memberfunction = void( Owner::* )();
template<class T>
void Register( T* obj, Memberfunction<T> function ) {
functions.push_back( std::bind( function, obj ) );
}
这工作得很好。但现在我想支持具有单个参数的函数,因为我不想为每个参数类型指定一个成员函数,我想再次使用模板。
template<class Owner, class Param>
using Memberfunction = void( Owner::* )( Param );
template<class T>
void Register( T* obj, Memberfunction<T,float> function ) {
using namespace std::placeholders;
functions.push_back( std::bind( function, obj, _1 ) );
}
到目前为止效果很好,但我不想为一个或没有参数指定成员函数,所以我想使用void 作为Memberfunction 的第二个参数,但这会导致内部编译器错误,所以我猜这不起作用。
有趣的是Memberfunction<Foo,void> bar = &Foo::Bar;导致以下错误:
cannot convert from 'void (__thiscall Foo::* )(void)' to 'void (__thiscall Foo::* )(void)'
现在回答我的问题:
是否有可能为此使用std::function?
如果这不起作用,我可以避免指定至少两个成员函数类型吗?
提前感谢您的帮助。
【问题讨论】:
-
我只是好奇,你有什么理由不想在调用
Register函数时使用std::bind,即Register(std::bind(...))? -
这也是我的一个想法,但我想让该功能尽可能易于使用。而且我认为必须使用
std::bind来注册回调函数并不像使用成员函数那样直观。我自己也很长时间不知道这个,改用lamdas封装函数调用,这不是我觉得最好的做法。 -
好吧,如果你只是传递了可调用对象,那么对你来说会容易得多 :)。然后也可以使用其他可调用对象,如非成员函数或 lambdas。
标签: c++ function templates callback member