这里有没有人使用Boost.Preprocessor库的数据类型来实现像X-macro这样的东西?
答案 0 :(得分:3)
我只是抬头看看X-Macro应该是什么,我想我做了类似你所要求的事情。
我想要做的是轻松快速地支持一系列相似类的序列化。我遇到的问题是我必须将一些运行时信息(一个int)转换为编译时类型(一个类)才能进行序列化。我本可以编写几个case语句来完成这项工作,但这意味着每次我想添加一个类时都必须更新几个函数。
为了解决这个问题,我首先定义了包含映射的a sequence tuples:
#define WIN_MESSAGE_TYPE_SEQ \
((EM_REPLACESEL, em_replacesel))((WM_CHAR, wm_char)) //...
大写名称是包含int的定义,小写名称是我在其他地方定义的类。
然后我可以将这个序列与一些Boost preprocessors一起使用,为我生成各种代码。例如,要获得类的前向声明,我可以这样做:
#define WIN_MESSAGE_TYPE_BUILD_MACRO(r, _data_, _elem_) \
class BOOST_PP_TUPLE_ELEM(2,1,_elem_);
BOOST_PP_SEQ_FOR_EACH(WIN_MESSAGE_TYPE_BUILD_MACRO, BOOST_PP_NIL, WIN_MESSAGE_TYPE_SEQ)
#undef WIN_MESSAGE_TYPE_BUILD_MACRO
要运行时编译时间映射,我会生成一系列case语句,如下所示:
#define WIN_MESSAGE_TYPE_BUILD_MACRO(r, _data_, _elem_) \
case BOOST_PP_TUPLE_ELEM(2,0,_elem_): return win_message_serializer<BOOST_PP_TUPLE_ELEM(2,1,_elem_)>::serialize(msg, o_arch);
template <typename Archive>
void serialize_win_message (p_win_message_base msg, Archive& o_arch) {
message_type_t message_type = msg->type();
switch (message_type) {
// This will generate a series of case statement for each message type that will invoke
// the serializer for the correct types.
BOOST_PP_SEQ_FOR_EACH(WIN_MESSAGE_TYPE_BUILD_MACRO, BOOST_PP_NIL, WIN_MESSAGE_TYPE_SEQ)
default: //...
};
}
#undef WIN_MESSAGE_TYPE_BUILD_MACRO
整个代码涉及的内容远不止这些,但是这仍然可以让您了解如何使用Boost预处理器生成代码。在我的示例中,我可以通过简单地更新序列来快速轻松地为类添加序列化支持。
请注意,使用Boost预处理器不会生成非常易读的代码,因此我尝试使每个宏使用的宏尽可能简单。如果有人在这个问题上找到更优雅的解决方案,我也不会感到惊讶。这就是我想出的个人项目,我不介意额外的复杂性。