我正在尝试创建一个宏,我可以使用该宏来自动为作用域枚举创建字符串化函数。我不是特别喜欢使用宏,而是一直在研究Boost.Fusion库的代码以获取灵感(特别是BOOST_FUSION_ADAPT_STRUCT)。当枚举具有默认值(从零开始的整数序列)时,我有一个可行的实现:
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#define XSTR(s) STR(s)
#define STR(s) #s
#define ENUM_FLAG(r, data, elemName) elemName,
#define ENUM_CASE(r, data, elemName) case data::elemName: return XSTR(elemName);
#define STRINGIFIED_ENUM(NAME_SEQ, \
ATTRIBUTES_SEQ) \
enum class NAME_SEQ { \
BOOST_PP_SEQ_FOR_EACH(ENUM_FLAG,,ATTRIBUTES_SEQ) \
SIZE = BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ) \
}; \
std::string enumToString(const NAME_SEQ& e) { \
switch(e) { \
BOOST_PP_SEQ_FOR_EACH(ENUM_CASE,NAME_SEQ,ATTRIBUTES_SEQ) \
default: return ""; \
} \
}
这是大肠菌病some example usage。
但是,对于我的目的而言,这还不够完整:我需要一个允许自定义枚举值的版本,并且我希望能够使用类似
的名称进行调用STRINGIFIED_CUSTOM_ENUM(myEnum, (a,1)(b,3)(c,5))
我知道这应该可行,因为这大致是BOOST_FUSION_DEFINE_STRUCT和BOOST_FUSION_ADAPT_STRUCT的签名(尽管我无法在boost源代码中使这些宏的首尾相接)。但是,到目前为止,我只能解决需要将序列的每个元素放在括号中的解决方案:
STRINGIFIED_CUSTOM_ENUM(myEnum, ((a,1))((b,3))((c,5)))
一个示例是here on coliru,它使用类似这样的代码(请注意,我现在只是在这里调用宏STRINGIFIED_ENUM,因为我现在只是对其进行单独测试:
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#define XSTR(s) STR(s)
#define STR(s) #s
#define ELEM_PAIR_NAME(elemPair) BOOST_PP_TUPLE_ELEM(2,0,elemPair)
#define ELEM_PAIR_VALUE(elemPair) BOOST_PP_TUPLE_ELEM(2,1,elemPair)
#define ENUM_FLAG(r, data, elemPair) ELEM_PAIR_NAME(elemPair) = ELEM_PAIR_VALUE(elemPair),
#define ENUM_CASE(r, data, elemPair) case data::ELEM_PAIR_NAME(elemPair): return XSTR(ELEM_PAIR_NAME(elemPair));
#define STRINGIFIED_ENUM(NAME_SEQ, \
ATTRIBUTES_SEQ) \
enum class NAME_SEQ { \
BOOST_PP_SEQ_FOR_EACH(ENUM_FLAG,,ATTRIBUTES_SEQ) \
SIZE = BOOST_PP_SEQ_SIZE(ATTRIBUTES_SEQ) \
}; \
std::string enumToString(const NAME_SEQ& e) { \
switch(e) { \
BOOST_PP_SEQ_FOR_EACH(ENUM_CASE,NAME_SEQ,ATTRIBUTES_SEQ) \
default: return ""; \
} \
}
这具有a)工作和b)非常简单的优点,但是我发现不得不添加这些多余的括号非常令人讨厌。顺便说一句,如果我将它们带走,类似
的错误main.cpp:24:40: error: macro "BOOST_PP_SEQ_SIZE_0" passed 2 arguments, but takes just 1
STRINGIFIED_ENUM(myEnum,(a,1)(b,3)(c,5))
等是不可避免的。我认为这里发生了正常的宏事件,在没有多余括号的情况下,宏将逗号视为宏参数之间的定界符,而不是嵌套宏参数的一部分。
是否有一种很简单的方法来克服这一障碍,而最好是尽可能地减少宏嵌套?