这是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>();
上失败了
注意:模板参数扣除/替换失败:
不应该调用默认处理程序吗?
答案 0 :(得分:1)
你的方法应该是这样的:
void handle(MSG_TYPES type) {
switch (type) {
case MSG1: handle_message<MSG1>();
case MSG2: handle_message<MSG2>();
}
}
答案 1 :(得分: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;
}
此示例将运行时值与每个枚举值进行比较,并执行匹配的特化(如果存在)。这可以通过使用二进制搜索进行优化,一旦找到值就返回,等等。
答案 2 :(得分:1)
又一种可能的实施......
unordered_map<int, function<void(void)>> handlers
{
{1, [](){cout << "Handler 1" << endl;}},
{2, [](){cout << "Handler 2" << endl;}},
{3, [](){cout << "Handler 3" << endl;}}
};
然后,当你想给你的处理程序调用一个值为&#39; i&#39; ...
handlers[i]();
但做IMO最好的事情是使用switch语句。另外,如果您要使用枚举,我建议您使用enum classes。