模板处理程序方法调度程序

时间:2016-05-16 20:45:46

标签: c++ templates c++11

这是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>();上失败了
  

注意:模板参数扣除/替换失败:

不应该调用默认处理程序吗?

3 个答案:

答案 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;
}

live example

此示例将运行时值与每个枚举值进行比较,并执行匹配的特化(如果存在)。这可以通过使用二进制搜索进行优化,一旦找到值就返回,等等。

答案 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