C++ 如何根据预定义宏(C+;+;预处理器)组合有效令牌?
假设一些标记C++ 如何根据预定义宏(C+;+;预处理器)组合有效令牌?,c++,macros,c-preprocessor,C++,Macros,C Preprocessor,假设一些标记FOO、BAR和DUD(可能更多)已定义或未定义。我想要一个生成有效扩展名的宏EXTEND(name),例如 #define FOO #undef BAR #define DUD EXTEND(object) 扩展到 object_foo_dud 如果存在n宏标记(如FOO、BAR、和DUD),是否可以用少于O(2n)行的行编写宏EXTEND?我认为O(n)线应该是可能的,但是怎么可能呢 我试过这个: #ifdef FOO # define ExtFOO(name) name
FOO
、BAR
和DUD
(可能更多)已定义或未定义。我想要一个生成有效扩展名的宏EXTEND(name)
,例如
#define FOO
#undef BAR
#define DUD
EXTEND(object)
扩展到
object_foo_dud
如果存在n
宏标记(如FOO
、BAR
、和DUD
),是否可以用少于O(2n)行的行编写宏EXTEND
?我认为O(n)线应该是可能的,但是怎么可能呢
我试过这个:
#ifdef FOO
# define ExtFOO(name) name ## _foo
#else
# define ExtFOO(name) name
#endif
#ifdef BAR
# define ExtBAR(name) ExtFOO(name) ## _bar
#else
# define ExtBAR(name) ExtFOO(name)
#endif
#ifdef DUD
# define ExtDUD(name) ExtBAR(name) ## _dud
#else
# define ExtDUD(name) ExtBAR(name)
#endif
#define EXTEND(name) ExtDUD(name)
但是
test.cc:26:5:错误:粘贴格式为“)\u dud”,是无效的预处理令牌扩展(对象)
^
##
运算符连接两个预处理令牌,并且必须生成单个有效令牌。例如,C99规范第6.10.3.3节:
对于类对象宏调用和类函数宏调用,在创建替换列表之前
重新检查是否有更多要替换的宏名称,##
预处理标记的每个实例
在替换列表中(不是从参数中)删除,并执行前面的预处理
令牌与以下预处理令牌连接。Placemarker预处理令牌是专门处理的:两个Placemarker的串联产生单个Placemarker预处理令牌,Placemarker与非Placemarker预处理令牌的串联产生非Placemarker预处理令牌如果结果不是有效的预处理标记,则行为未定义。生成的标记可用于进一步的宏替换。未指定##
运算符的求值顺序
因此扩展名ExtBAR(name)##(dud
无效,因为它将生成ExtBAR(object)(dud
)
我将采用以下方法:
#ifdef FOO
# define ValFOO _foo
#else
# define ValFOO
#endif
#ifdef BAR
# define ValBAR _bar
#else
# define ValBAR
#endif
#ifdef DUD
# define ValDUD _dud
#else
# define ValDUD
#endif
#define CONCAT(a, b, c, d) a ## b ## c ## d
#define XCONCAT(a, b, c, d) CONCAT(a, b, c, d)
#define EXTEND(name) XCONCAT(name, ValFOO, ValBAR, ValDUD)
需要中间的XCONCAT
步骤,因为如果宏参数使用##
##
运算符连接两个预处理标记,并且必须生成单个有效标记,则宏参数不会展开。例如,C99规范第6.10.3.3节:
对于类对象宏调用和类函数宏调用,在创建替换列表之前
重新检查是否有更多要替换的宏名称,##
预处理标记的每个实例
在替换列表中(不是从参数中)删除,并执行前面的预处理
令牌与以下预处理令牌连接。Placemarker预处理令牌是专门处理的:两个Placemarker的串联产生单个Placemarker预处理令牌,Placemarker与非Placemarker预处理令牌的串联产生非Placemarker预处理令牌如果结果不是有效的预处理标记,则行为未定义。生成的标记可用于进一步的宏替换。未指定##
运算符的求值顺序
因此扩展名ExtBAR(name)##(dud
无效,因为它将生成ExtBAR(object)(dud
)
我将采用以下方法:
#ifdef FOO
# define ValFOO _foo
#else
# define ValFOO
#endif
#ifdef BAR
# define ValBAR _bar
#else
# define ValBAR
#endif
#ifdef DUD
# define ValDUD _dud
#else
# define ValDUD
#endif
#define CONCAT(a, b, c, d) a ## b ## c ## d
#define XCONCAT(a, b, c, d) CONCAT(a, b, c, d)
#define EXTEND(name) XCONCAT(name, ValFOO, ValBAR, ValDUD)
需要中间的XCONCAT
步骤,因为如果宏参数使用##
##
运算符连接两个预处理标记,并且必须生成单个有效标记,则宏参数不会展开。例如,C99规范第6.10.3.3节:
对于类对象宏调用和类函数宏调用,在创建替换列表之前
重新检查是否有更多要替换的宏名称,##
预处理标记的每个实例
在替换列表中(不是从参数中)删除,并执行前面的预处理
令牌与以下预处理令牌连接。Placemarker预处理令牌是专门处理的:两个Placemarker的串联产生单个Placemarker预处理令牌,Placemarker与非Placemarker预处理令牌的串联产生非Placemarker预处理令牌如果结果不是有效的预处理标记,则行为未定义。生成的标记可用于进一步的宏替换。未指定##
运算符的求值顺序
因此扩展名ExtBAR(name)##(dud
无效,因为它将生成ExtBAR(object)(dud
)
我将采用以下方法:
#ifdef FOO
# define ValFOO _foo
#else
# define ValFOO
#endif
#ifdef BAR
# define ValBAR _bar
#else
# define ValBAR
#endif
#ifdef DUD
# define ValDUD _dud
#else
# define ValDUD
#endif
#define CONCAT(a, b, c, d) a ## b ## c ## d
#define XCONCAT(a, b, c, d) CONCAT(a, b, c, d)
#define EXTEND(name) XCONCAT(name, ValFOO, ValBAR, ValDUD)
需要中间的XCONCAT
步骤,因为如果宏参数使用##
##
运算符连接两个预处理标记,并且必须生成单个有效标记,则宏参数不会展开。例如,C99规范第6.10.3.3节:
对于类对象宏调用和类函数宏调用,在创建替换列表之前
重新检查是否有更多要替换的宏名称,##
预处理标记的每个实例
在替换列表中(不是从参数中)删除,并执行前面的预处理
令牌与以下预处理令牌连接。Placemarker预处理令牌是专门处理的:两个Placemarker的串联产生单个Placemarker预处理令牌,Placemarker与非Placemarker预处理令牌的串联产生非Placemarker预处理令牌如果结果不是有效的预处理标记,则行为未定义。生成的标记可用于进一步的宏替换。未指定##
运算符的求值顺序
因此扩展名ExtBAR(name)##(dud
无效,因为它将生成ExtBAR(object)(dud
)
我将采用以下方法:
#ifdef FOO
# define ValFOO _foo
#else
# define ValFOO
#endif
#ifdef BAR
# define ValBAR _bar
#else
# define ValBAR
#endif
#ifdef DUD
# define ValDUD _dud
#else
# define ValDUD
#endif
#define CONCAT(a, b, c, d) a ## b ## c ## d
#define XCONCAT(a, b, c, d) CONCAT(a, b, c, d)
#define EXTEND(name) XCONCAT(name, ValFOO, ValBAR, ValDUD)
中间XCONCAT
步骤为nee