文档章节

C++ boost.preprocessor自动定义枚举

 百之姓
发布于 2016/05/15 01:03
字数 453
阅读 57
收藏 1

想定义一个宏,实现目的如下:

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测试通过。

 

 

© 著作权归作者所有

共有 人打赏支持
粉丝 0
博文 1
码字总数 453
作品 0
大兴
程序员
私信 提问
C++ 中命名空间的 5 个常见用法

原文出处:CppDepend Team 译文出处:王江平 译者注:可能很多程序员对C++已经非常熟悉,但是对命名空间经常使用到的地方还不是很明白,这篇文章就针对命名空间这一块做了一个叙述。 命名空间...

CppDepend Team
2017/06/16
0
0
C++ Primer Plus(四)——复合类型

只能在定义数组时才能初始化,不能将一个数组赋值给另一个数组,但可以使用下标分别赋值给数组元素,但可以将一个string对象赋值给另一个string对象 如果只对数组的一部分初始化,其他元素自...

吃一堑消化不良
2015/11/06
0
0
Thrift RPC 系列教程(1)——Thrift语言

Thrift不是严格意义上的编程语言,但是却胜过很多编程语言,充满了美感。 基础数据类型 Thrift 这门编程语言提供了如下几种基础的数据类型: bool: A boolean value (true or false) byte: ...

浮生若梦的编程
11/05
0
0
C与C++对于全局变量的不同处理之处

下面看看我犯的错误: 当时写了一个类似于下面的枚举: #ifndef TESTENUMH_ #define TESTENUMH_ enum { TESTFLAG1E, TESTFLAG2E, TESTFLAGNR } TEST_E; #endif 当时在enum关键字前面遗漏了“...

十分爱
2012/01/22
0
1
Thrift学习笔记—IDL基本类型

原文地址:http://zhwen.org/xlog/?p=658 thrift 采用IDL(Interface Definition Language)来定义通用的服务接口,并通过生成不同的语言代理实现来达到跨语言、平台的功能。在thrift的IDL中...

helight
2014/01/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Dubbo分析之Cluster层

系列文章 Dubbo分析Serialize层 Dubbo分析之Transport层 Dubbo分析之Exchange 层 Dubbo分析之Protocol层 前言 紧接上文Dubbo分析之Protocol层,本文继续分析dubbo的cluster层,此层封装多个提...

ksfzhaohui
17分钟前
0
0
linux Ubuntu 安装 hyperledger fabric

一、apt-get update 二、安装docker sudo apt-get install docker.io 如果安装报错:E: Unable to locate package,请执行第一条。 # docker -v Docker version 1.6.2, build 7c8fca2 # dock......

八戒八戒八戒
20分钟前
1
0
神经网络基础及Keras入门

神经网络定义 人工神经网络,简称神经网络,在机器学习和认知科学领域,是一种模仿生物神经网络(动物的中枢神经系统,特别是大脑)的结构和功能的数学模型或计算模型,用于对函数进行估计或...

Python女神
21分钟前
1
0
Pycharm上Django的使用 Day9

编辑条目: 1.创建edit_entry的URL模式 形参entry_id存储在URL中传递的ID,这个URL模式将预期匹配的请求发送给视图函数edit_entry() 2.编写视图函数edit_entry() 1处获取用户要修改的条目对象...

不会TC的猫
21分钟前
1
0
夹点getGripPoints/捕捉点getOsnapPoints

已知圆外一点,以及圆心半径,求圆的切点: 方法1: (b-y/a-x)*(n-y/m-x)=-1(a-x)平方+(b-y)平方=r平方联立方程组求解 方法1: CPoint CalcQieDian(CPoint ptCenter, CPoint ptOutside, do...

一个小妞
33分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部