我有一个带有两个参数的模板类:
template<class TEvent, class TData>
class EventPool {
public:
using EventObserver = std::function<void(const TData &)>;
using EventData = TData;
using EventType = TEvent;
public:
EventObserverId observe(TEvent event, EventObserver &&observer) { ... }
void deleteObserver(EventObserverId observerId) { ... }
void dispatch(TEvent event, const TData &data) { ... }
};
Run Code Online (Sandbox Code Playgroud)
我还有另一个存储许多池的容器类:
class EventSystem {
using CollisionPool = EventPool<CollisionEvent, CollisionData>;
using MouseButtonPool = EventPool<MouseButtonEvent, MouseButtonData>;
using KeyboardPool = EventPool<KeyboardButtonEvent, KeyboardButtonData>;
public:
private:
std::tuple<CollisionPool, MouseButtonPool, KeyboardPool> mPools;
};
Run Code Online (Sandbox Code Playgroud)
现在,我想创建一个基于模板的函数,它自动推断正确的池并调用池内的函数。例如:
template<class TEvent>
EventObserverId observe(TEvent event, DeriveThePoolHere::EventObserver &&observer) {
auto &pool = getPoolByFromEventType<TEvent>();
return pool.observe(event, observer);
}
template<class TEvent>
void deleteObserver(TEvent event, EventObserverId observerId) {
auto &pool = getPoolFromEevntType<TEvent>();
pool.deleteObserver(observerId);
}
void dispatch(TEvent event, const DeriveThePoolHere::EventData &data) {
auto &pool = getPoolFromEventType<TEvent>();
pool.dispatch(event, data);
}
Run Code Online (Sandbox Code Playgroud)
如果我能以某种方式创建一个将事件映射到事件数据的类型映射,我就可以解决这个问题,但我不知道如何在 C++ 中做到这一点。
if constexpr
在and的帮助下std::apply
(需要 c++17)
也许像这样:
template<typename TPool, typename TEvent, typename TData>
void dispatchIfMatch(TPool& pool, TEvent event, const TData& data) {
if constexpr(std::is_same<TEvent, typename TPool::EventType>::value) {
pool.dispatch(event, data);
}
}
template<typename TEvent, typename TData>
void dispatch(EventSystem& esys, TEvent event, const TData& data) {
std::apply(
[&](auto&&... args) {
((dispatchIfMatch(args, event, data)), ...);
}, esys.mPools);
}
Run Code Online (Sandbox Code Playgroud)
在这里测试:http://coliru.stacked-crooked.com/a/2c2231c860d8023c