在C中编译时间映射“搜索”

我有下一个简化的回调映射.如果代码包含一些错误,请原谅我,但它是一个非常简化的实际代码版本,可以在这里重现它.

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(&param);
        }
    }

    std::map<std::type_index, std::vector<std::unique_ptr<CallbackBaseType>>> _callbacks;
};

在这个例子中,我可以通过调用Call(param)成员函数来调用具有相同参数类型的所有函数.我的问题是_callbacks中的搜索是在运行时完成的,即使密钥在编译时已知.

我无法根据类型的type_index使回调列表静态本地化为模板函数,因为我需要跟踪Remove(T * obj)函数的所有对象.

您知道如何使内部结构能够避免此运行时开销吗?

最佳答案 您可以将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(&param);
        }
    }

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);
点赞