2013-03-22 27 views
4

我有下一個簡化的回調映射。請原諒,如果代碼包含一些錯誤,但它是一個非常簡化的實際代碼版本,可以在這裏重現它。在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中的搜索是在運行時完成的,即使在編譯時已知密鑰。

由於我需要跟蹤Remove(T* obj)函數的所有對象,因此我無法將回調列表設置爲基於type_index類型的模板函數的靜態本地。

你知道如何讓內部結構能夠避免這種運行時間開銷?

+2

如果在編譯時不知道映射,那麼搜索將如何進行? – Pubby 2013-03-22 14:48:54

+0

這就是爲什麼我把標題中的「搜索」,因爲它不是一個真正的搜索......我認爲這是缺乏靈感(標題是非常糟糕的)我只需要一種方法來獲取類型的回調列表並獲得所有已註冊回調的清單,以便能夠刪除死者。 – Felics 2013-03-22 14:54:21

+0

你可以用MPL完成它,但你的回調不應該是T的成員函數。他們應該是一些類型。 – kassak 2013-03-22 15:04:56

回答

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