问题描述
我想为我的游戏写一个事件系统。我的事件管理器将存储的回调可以是普通函数以及函子。我还需要能够比较函数/函子,所以我知道哪一个我需要断开与事件管理器。
I'm trying to write an event system for my game. The callbacks that my event manager will store can be both plain functions as well as functors. I also need to be able to compare functions/functors so I know which one I need to disconnect from the event manager.
•最初我尝试使用boost :: function;它完美地处理函数和函数,除非它没有操作符==,所以如果我想,我不能删除回调。
• Initially I tried using boost::function; it handles functions and functors perfectly well, except it has no operator==, so I can't remove callbacks if I want to.
class EventManager
{
typedef boost::function<void (boost::weak_ptr<Event>)> Callback;
std::map<Event::Type, std::vector<Callback>> eventHandlerMap_;
};
•我也尝试使用boost :: signal,但这也给我一个编译问题==:
• I also tried using boost::signal, but that also gives me a compilation problem related to operator==:
void test(int c) {
std::cout << "test(" << c << ")";
}
struct Functor
{
void operator()(int g) {
std::cout << "Functor::operator(" << g << ")";
}
};
int main()
{
boost::signal<void (int)> sig;
Functor f;
sig.connect(test);
sig.connect(f);
sig(7);
sig.disconnect(f); // Error
}
有关如何实现这一点的任何其他建议?或者也许我可以使boost :: function或boost :: signal工作? (我宁愿使用boost :: function虽然,因为我听说信号对于小集合的项目是相当缓慢。)
Any other suggestions about how I might implement this? Or maybe how I can make either boost:: function or boost::signal work? (I'd rather use boost:: function though, since I've heard signal is rather slow for small collections of items.)
Edit:这是我想要的EventManager的接口。
This is the interface of that I'd like EventManager to have.
class EventManager
{
public:
void addEventHandler(Event::Type evType, Callback func);
void removeEventHandler(Event::Type evType, Callback func);
void queueEvent(boost::shared_ptr<Event> ev);
void dispatchNextEvent();
};
推荐答案
一个小的模板魔法和事情变得简单(r):
No matter, I found the solution. A little template magic and things become simple(r):
template<typename F>
void EventManager::removeEventHandler(Event::Type evType, F func)
{
auto compare = [func](const Callback& other) -> bool {
F const* f = other.target<F>();
if (f == nullptr) return false;
return *f == func;
};
std::vector<Callback>& callbacks = ...;
auto pend = std::remove_if(callbacks.begin(), callbacks.end(), compare);
callbacks.erase(pend, callbacks.end());
}
template<typename R, typename F, typename L>
void EventManager::removeEventHandler(
Event::Type evType, const boost::_bi::bind_t<R, F, L>& func)
{
auto compare = [&func](const Callback& other) -> bool {
auto const* f = other.target<boost::_bi::bind_t<R, F, L>>();
if (f == nullptr) return false;
return func.compare(*f);
};
std::vector<Callback>& callbacks = ...;
auto pend = std::remove_if(callbacks.begin(), callbacks.end(), compare);
callbacks.erase(pend, callbacks.end());
}
我需要单独处理Boost.Bind对象,因为 operator ==
实际上不会对Bind对象进行比较,但会产生一个新的函子,比较其他两个函数的结果()。要比较Boost.Bind,必须使用成员函数 compare()
。
I need to handle Boost.Bind objects separately because operator==
doesn't actually do comparison for Bind objects, but produce a new functor that compares the result of the other two (read more). To compare Boost.Bind you have to use the member function compare()
.
类型 boost :: _ bi :: bind_t
似乎是一个内部类型的Boost(我猜这是命名空间'_bi'中的下划线意味着),但它应该是安全的使用它作为所有重载 boost :: function_equal
也使用此类型()。
The type boost::_bi::bind_t
seems to be an internal type of Boost (I guess that's what the underscore in namespace '_bi' means), however it should be safe to use it as all overloads of boost::function_equal
also use this type (reference).
此代码将适用于所有类型的函子,只要有 operator ==
定义比较,或者如果您使用Boost.Bind。我有一个表面看看 std :: bind
(C + + 0x),但是似乎不可比较,所以它不会与代码一起工作贴上。
This code will work for all types of functors as long as there is an operator==
defined that does comparison, or if you're using Boost.Bind. I had a superficial look into std::bind
(C++0x), but that doesn't seem to be comparable, so it won't work with the code I posted above.
这篇关于消息系统:回调可以是任何东西的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!