Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何根据预定义宏(C+;+;预处理器)组合有效令牌?_C++_Macros_C Preprocessor - Fatal编程技术网

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