2016-05-16 59 views
1

這是this問題的延續。模板處理程序方法調度程序

我有不同的模板方法,分別用於不同類型的消息,使用非類型模板參數和模板專業化:

namespace Handlers { 

enum MSG_TYPES { 
    MSG1, 
    MSG2 

}; 

template<MSG_TYPES> 
void handle_message() { 
    // Default handler : not defined type 
} 


template<> 
void handle_message<MSG1>() { 
    cout << "Handle 1"; 
} 

template<> 
void handle_message<MSG2>() { 
    cout << "Handle 2"; 
} 

現在,我想有一些其他的方法來派遣正確的處理程序。喜歡的東西

template<typename T> 
void handle(T t) { 
    try { 
     handle_message<T>(); 
    } catch(...) { 

    } 
} 

可能被調用像

int i = 0; 
Handlers::handle(static_cast<Handlers::MSG_TYPES>(i)); 

所以,這個調度員怎麼可能實現呢?

PS:前面的代碼失敗的handle_message<T>();因爲

注:模板參數推導/置換失敗:

應該不是默認的處理程序中調用?

+4

要調用的函數是一個*編譯時*的決定,但它看起來像你的'我'值可能不知道,直到*運行時*。 – aschepler

+0

@aschepler是的,我混合運行時和編譯時間。所以,我留下了一個類似開關的結構來決定一旦我知道消息ID(i)時要調用哪個方法? – perencia

+1

您正在將類型傳遞給期望枚舉值的模板;這並不奇怪,它試圖推斷出這個論點。 –

回答

1

你的方法應該是這樣的:

void handle(MSG_TYPES type) { 
    switch (type) { 
     case MSG1: handle_message<MSG1>(); 
     case MSG2: handle_message<MSG2>(); 
    } 
} 
1

如果你不想自己寫switch語句,你就可以使用例如在編譯時的迭代升壓:: MPL:

#include <iostream> 

#include <boost/mpl/for_each.hpp> 
#include <boost/mpl/range_c.hpp> 

namespace Handlers { 

enum MSG_TYPES { 
    MSG1, 
    MSG2, 
    LAST 
}; 


template<MSG_TYPES> 
void handle_message() { 
} 

template<> 
void handle_message<MSG_TYPES::MSG1>() { 
    std::cout << "Handle 1" << std::endl; 
} 

template<> 
void handle_message<MSG_TYPES::MSG2>() { 
    std::cout << "Handle 2" << std::endl; 
} 


struct runtime_handler 
{ 
    std::size_t i; 
    bool& found; 

    runtime_handler(std::size_t i, bool& found) : i(i), found(found){} 

    template < typename Index > 
    void operator() (Index&) 
    { 
    if(i == Index::value) 
    { 
     Handlers::handle_message<Index::value>(); 
     found = true; 
    } 
    } 
}; 

void handle(std::size_t i) 
{ 
    bool found = false; 
    boost::mpl::for_each<boost::mpl::range_c<Handlers::MSG_TYPES, Handlers::MSG1, Handlers::LAST> >(runtime_handler(i, found)); 

    if (!found) { 
     std::cout << "could not find handler for id = " << i << std::endl; 
    } 
} 
} 


int main() 
{ 
    Handlers::handle(0); 
    Handlers::handle(1); 
    Handlers::handle(10); 
    return 0; 
} 

live example

此示例運行時的值與每個枚舉值進行比較,並且如果存在執行匹配專業化。這可以通過使用二進制搜索,返回一次值進行優化,發現等

+0

非常有趣! – perencia

1

另一種可能的實現......

unordered_map<int, function<void(void)>> handlers 
{ 
    {1, [](){cout << "Handler 1" << endl;}}, 
    {2, [](){cout << "Handler 2" << endl;}}, 
    {3, [](){cout << "Handler 3" << endl;}} 
}; 

然後,當你想打電話給你的處理程序的值'我'...

handlers[i](); 

但是做IMO的最好的事情是使用switch語句。另外,如果你打算使用枚舉,我可以推薦你使用enum classes