C++ boost.preprocessor自动定义枚举
2016-05-15 01:03
585 查看
想定义一个宏,实现目的如下:
ZME_PP_ENUM_DEF(name, ...);
展开之后是:
enum E_name
{
E_name_NULL,
E_name_0,
E_name_1,
.......
E_name_COUNT
};
例如:ZME_PP_ENUM_DEF(TST, A, B, C, D);
展开之后是:
enum E_TST
{
E_TST_NULL,
E_TST_A,
E_TST_B,
E_TST_C,
E_TST_D,
E_TST_COUNT
};
具体的实现代码如下:
#define ZME_LOOP_PRED_4(r, state) \
BOOST_PP_LESS(\
BOOST_PP_TUPLE_ELEM(4, 0, state), \
BOOST_PP_TUPLE_ELEM(4, 1, state) \
) \
/**/
#define ZME_LOOP_OP_4(r, state) \
(\
BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(4, 0, state)), \
BOOST_PP_TUPLE_ELEM(4, 1, state), \
BOOST_PP_TUPLE_ELEM(4, 2, state), \
BOOST_PP_TUPLE_ELEM(4, 3, state) \
) \
/**/
#define ZME_LOOP_FOR4(opt, arg, ...) BOOST_PP_FOR((0, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__), arg), ZME_LOOP_PRED_4, ZME_LOOP_OP_4, opt)/**/
/*定义循环方法:*/
方法1:
#define ZME_PP_ENUM_DEF_FOR_DO(r, state) BOOST_PP_CAT(BOOST_PP_LIST_AT((BOOST_PP_TUPLE_ELEM(4, 3, state),BOOST_PP_NIL), 0),BOOST_PP_LIST_AT(BOOST_PP_TUPLE_ELEM(4, 2, state), BOOST_PP_TUPLE_ELEM(4, 0, state))),/**/
方法2:
#define ZME_PP_ENUM_DEF_FOR_DO(r, state) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(4, 3, state), \
BOOST_PP_LIST_AT(BOOST_PP_TUPLE_ELEM(4, 2, state), BOOST_PP_TUPLE_ELEM(4, 0, state))),/**/
方法2中正常理解BOOST_PP_TUPLE_ELEM(4, 3, state)展开之后就是arg,但是这种方法在linux系统(我用的是KALI2.0)下是没问题的,但是在VS2013下,编译错误:
错误 1 error C2143: 语法错误 : 缺少“}”(在“(”的前面)
错误 2 error C2143: 语法错误 : 缺少“;”(在“<L_TYPE_raw>”的前面)
错误 3 error C2059: 语法错误:“<L_TYPE_raw>”
错误 4 error C2143: 语法错误 : 缺少“;”(在“}”的前面)
错误 5 error C2065: “E_TST_NULL”: 未声明的标识符
.........
BOOST_PP_CAT在BOOST_PP_FOR中使用好像有问题。解决方法就是使用方法1,先把BOOST_PP_TUPLE_ELEM(4, 3, state)也就是arg转化为BOOST_PP_LIST,然后再取其第一个值。
/* 定义枚举结构 */
#define ZME_PP_ENUM_DEF(name, ...) enum E_##name { \
E_##name##_NULL, \
ZME_LOOP_FOR4(ZME_PP_ENUM_DEF_FOR_DO, E_##name##_, __VA_ARGS__) \
E_##name##_COUNT \
};/**/
/********************************************************************************/
/* OK, 这样就可以定义我们的枚举了。*/
ZME_PP_ENUM_DEF(TST, A, B, C, D);
printf("ZME_PP_ENUM_DEF: %d, %d, %d, %d, %d, %d\n", E_TST_NULL, E_TST_A, E_TST_B, E_TST_C, E_TST_D, E_TST_COUNT);
win8.1+vs2013、kali2.0测试通过。
ZME_PP_ENUM_DEF(name, ...);
展开之后是:
enum E_name
{
E_name_NULL,
E_name_0,
E_name_1,
.......
E_name_COUNT
};
例如:ZME_PP_ENUM_DEF(TST, A, B, C, D);
展开之后是:
enum E_TST
{
E_TST_NULL,
E_TST_A,
E_TST_B,
E_TST_C,
E_TST_D,
E_TST_COUNT
};
具体的实现代码如下:
#define ZME_LOOP_PRED_4(r, state) \
BOOST_PP_LESS(\
BOOST_PP_TUPLE_ELEM(4, 0, state), \
BOOST_PP_TUPLE_ELEM(4, 1, state) \
) \
/**/
#define ZME_LOOP_OP_4(r, state) \
(\
BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(4, 0, state)), \
BOOST_PP_TUPLE_ELEM(4, 1, state), \
BOOST_PP_TUPLE_ELEM(4, 2, state), \
BOOST_PP_TUPLE_ELEM(4, 3, state) \
) \
/**/
#define ZME_LOOP_FOR4(opt, arg, ...) BOOST_PP_FOR((0, BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__), arg), ZME_LOOP_PRED_4, ZME_LOOP_OP_4, opt)/**/
/*定义循环方法:*/
方法1:
#define ZME_PP_ENUM_DEF_FOR_DO(r, state) BOOST_PP_CAT(BOOST_PP_LIST_AT((BOOST_PP_TUPLE_ELEM(4, 3, state),BOOST_PP_NIL), 0),BOOST_PP_LIST_AT(BOOST_PP_TUPLE_ELEM(4, 2, state), BOOST_PP_TUPLE_ELEM(4, 0, state))),/**/
方法2:
#define ZME_PP_ENUM_DEF_FOR_DO(r, state) BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(4, 3, state), \
BOOST_PP_LIST_AT(BOOST_PP_TUPLE_ELEM(4, 2, state), BOOST_PP_TUPLE_ELEM(4, 0, state))),/**/
方法2中正常理解BOOST_PP_TUPLE_ELEM(4, 3, state)展开之后就是arg,但是这种方法在linux系统(我用的是KALI2.0)下是没问题的,但是在VS2013下,编译错误:
错误 1 error C2143: 语法错误 : 缺少“}”(在“(”的前面)
错误 2 error C2143: 语法错误 : 缺少“;”(在“<L_TYPE_raw>”的前面)
错误 3 error C2059: 语法错误:“<L_TYPE_raw>”
错误 4 error C2143: 语法错误 : 缺少“;”(在“}”的前面)
错误 5 error C2065: “E_TST_NULL”: 未声明的标识符
.........
BOOST_PP_CAT在BOOST_PP_FOR中使用好像有问题。解决方法就是使用方法1,先把BOOST_PP_TUPLE_ELEM(4, 3, state)也就是arg转化为BOOST_PP_LIST,然后再取其第一个值。
/* 定义枚举结构 */
#define ZME_PP_ENUM_DEF(name, ...) enum E_##name { \
E_##name##_NULL, \
ZME_LOOP_FOR4(ZME_PP_ENUM_DEF_FOR_DO, E_##name##_, __VA_ARGS__) \
E_##name##_COUNT \
};/**/
/********************************************************************************/
/* OK, 这样就可以定义我们的枚举了。*/
ZME_PP_ENUM_DEF(TST, A, B, C, D);
printf("ZME_PP_ENUM_DEF: %d, %d, %d, %d, %d, %d\n", E_TST_NULL, E_TST_A, E_TST_B, E_TST_C, E_TST_D, E_TST_COUNT);
win8.1+vs2013、kali2.0测试通过。
相关文章推荐
- C++简单使用Jsoncpp来读取写入json文件
- GeekBand C++第一周学习感悟
- c++实验5
- c++作业5
- java语言,c语言,五子棋的实现(键盘输入坐标)。
- C++11: std::packaged_task
- c++学习笔记(2)——有关queue
- c语言学习笔记6之进制转换
- C++实现委托机制(一)
- C语言 - n的阶乘 递归
- xgboost C++ window编译问题解决与安装
- C++走向远洋——49(项目一2、复数类中的运算符重载、类的友元函数)
- C++静态成员(静态成员变量、静态成员函数)与正常成员互相调用的权限问题
- 关于vector在堆上还是在栈上的思考与vector.push_back()究竟放入的是什么
- C++走向远洋——48(项目一1、复数类中的运算符重载、类的成员函数)
- 17907955 2016-05-14 17:17:32 biss A - Summer Camp GNU C++11 Accepted 15 ms 2200 KB
- 第7周 C语言程序设计(新2版) 练习9/10 解释原理与大写变小写
- C++走向远洋——47(第十二周、运算符重载基础程序、阅读)
- C++数组在函数中的传递与返回
- C++之RAII惯用法