该解决方案必须可在 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);
}
...
};
即使是对我的设计进行彻底的返工,但使用类似的用法,以及每一个改进建议都会很好。谢谢