我有下一个简化的回调映射。如果代码包含一些错误,请原谅我,但这是一个非常简化的实际代码版本,可以在这里重现它。
struct CallbacksMap
{
template<typename T, typename U>
void Add(T* obj, void (T::*objCallback)(const U&))
{
CallbackBaseType* c = new CallbackType<T, U>(obj, objCallback);
_callbacks[std::type_index(typeid(U))].push_back(std::unique_ptr<CallbackBaseType>(c));
}
template<typename T>
void Remove(T* obj){...}
template<typename T>
void Call(const T& param)
{
std::vector<std::unique_ptr<T>>& callbacks = _callbacks[std::type_index(typeid(T))];
for(auto callback = callbacks.begin(); callback != callbacks.end(); ++callback)
{
(*callback)->Call(¶m);
}
}
std::map<std::type_index, std::vector<std::unique_ptr<CallbackBaseType>>> _callbacks;
};
在这个示例中,我可以通过调用Call(param)
成员函数来调用具有相同参数类型的所有函数。我的问题是_callbacks
中的搜索是在运行时完成的,即使密钥在编译时已知。
我无法根据类型的type_index使回调列表静态本地化为模板函数,因为我需要跟踪Remove(T* obj)
函数的所有对象。
您知道如何让内部结构能够避免这种运行时开销吗?
答案 0 :(得分:2)
您可以将CallbacksMap
设为模板:
template<typename T>
struct CallbacksMap
{
template<typename U>
static void Add(T* obj, void (T::*objCallback)(const U&))
{
CallbackBaseType* c = new CallbackType<T, U>(obj, objCallback);
auto& callbacks = callbacks();
callbacks.push_back(std::unique_ptr<CallbackBaseType>(c));
}
static void Remove(T* obj){...}
static void Call(const T& param)
{
auto& callbacks = callbacks();
for(auto callback = callbacks.begin(); callback != callbacks.end(); ++callback)
{
(*callback)->Call(¶m);
}
}
private:
std::vector<std::unique_ptr<CallbackBaseType>& callbacks()
{
static std::vector<std::unique_ptr<CallbackBaseType> _callbacks;
return _callbacks;
}
};
这样,类型查找由编译器完成。当然这意味着你必须通过使用类似的东西来调用回调:
template <typename T>
void CallCallbacks(const T& param)
{
CallbacksMap<T>(param);
}
CallCallbacks(param);