为基于整数id的回调映射编译时间类型生成器

时间:2013-11-05 13:55:01

标签: c++ boost

解决方案必须在gcc 4.2& vs2012sp1。

我需要实现一个回调系统。各种回调必须在CallbackMap中作为类型提供,以便人们可以使用类型而不是id。 ID必须是编译时常量,因为它用于各种编译时检查。回调必须能够通过其ID“查找”,查找在运行时进行。

附加约束: 我必须能够控制ID范围。例如,第一个ID可以是20。 id_type可能不是size_t而是16/32/64bit积分。

问题:随着这个CallbackMap的增长,改变它的人会更频繁地计算ID错误。我希望编译器可以为我计算,并且不管怎么说都可以注册回调。

当前解决方案的一个示例:

#include <boost/signals2/signal.hpp>
#include <map>

typedef size_t id_type;
typedef boost::signals2::signal<void()> sig_type;

#define REGISTER_CALLBACK(NAME) cb_map_[NAME.ID] = &NAME;

struct CallbackBase
{
  sig_type sig;
};

template <id_type N>
struct Callback : CallbackBase
{
  static const size_t ID = N;
};

struct CallbackMap
{
  Callback<1> cb1;
  Callback<2> cb2;
  Callback<3> cb3;

  CallbackMap()
  {
    REGISTER_CALLBACK(cb1);
    REGISTER_CALLBACK(cb2);
    REGISTER_CALLBACK(cb3);
  }

  CallbackBase& GetCallback(id_type id)
  { // I know, no checks here..
    return *cb_map_.find(id)->second;
  }

private:
  std::map<id_type, CallbackBase*> cb_map_;
};

int main()
{
  CallbackMap cb;

  // Register handlers for callbacks
  // cb.cb1.sig.connect(...)

  int incomingRuntimeId = 2;
  cb.GetCallback(incomingRuntimeId).sig();

  return 0;
}

我喜欢这样的东西(即使没有REGISTER_CALLBACK也更好):

struct CallbackMap
{
  DECLARE_CALLBACK(cb1);
  DECLARE_CALLBACK(cb2);
  DECLARE_CALLBACK(cb3);

  CallbackMap()
  {
    REGISTER_CALLBACK(cb1);
    REGISTER_CALLBACK(cb2);
    REGISTER_CALLBACK(cb3);
  }
  ...
};

即使对我的设计进行彻底的修改,但使用类似的设置也会很好,以及每一个改进的建议。 感谢

0 个答案:

没有答案