使用编译器定义的宏连接
Macro concatenation using compiler define
这应该很简单,但我正在努力弄清楚。我有PROJECT_NAME
作为编译器(g++
) -D
定义,我想把它与其他一些文本连接起来,形成一个命名空间名称。我目前的方法是:
#define VERSION_NAMESPACE PROJECT_NAME ## Versioning
对于我目前的项目,我期望VERSION_NAMESPACE
是Syren_DLLVersioning
。相反,我得到一个编译器错误:
error: 'PROJECT_NAMEVersioning' has not been declared
但是根据g++
调用,PROJECT_NAME
被正确定义:
ccache g++ ... -DPROJECT_NAME=Syren_DLL ...
为什么PROJECT_NAME
在连接发生之前没有被替换?
宏名称出现在##
操作符旁边时不会展开,因此您需要更多的间接层:
#define P_VERSION2(foo) foo ## Versioning
#define P_VERSION(foo) P_VERSION2(foo)
#define VERSION_NAMESPACE P_VERSION(PROJECT_NAME)
使PROJECT_NAME
被展开为P_VERSION
的参数,然后在P_VERSION2
中进行连接。
在第16.3.3节中[cpp。Concat],第3段,指定
对于类对象和类函数的宏调用,在重新检查替换列表以查找更多要替换的宏名之前,删除替换列表(不是来自参数)中的
##
预处理令牌的每个实例,并将前面的预处理令牌与下面的预处理令牌连接起来。
表示在替换列表上执行宏替换之前,将与##
预处理令牌相邻的预处理令牌连接在。因此,PROJECT_NAME
必须通过另一个(类函数)宏传递,以便将其替换并与Versioning
连接。
但是在16.3.1中[cpp。Subst],第1段,标准规定(强调由我添加)
在识别了类函数宏调用的参数之后,将进行参数替换。替换列表中的参数,除非前面有
#
或##
预处理令牌或后面有##
预处理令牌(见下文),否则在其中包含的所有宏都被展开后,将被相应的实参替换。在被替换之前,每个参数的预处理标记被完全宏替换,就好像它们构成了预处理文件的其余部分一样;没有其他预处理令牌可用。
,如果宏参数与##
预处理令牌相邻,则不受进一步宏展开的影响。因此,接收PROJECT_NAME
作为参数的类函数宏不能直接将其参数与Versioning
连接起来,但要扩展PROJECT_NAME
,它必须调用另一个类函数宏来最终进行连接。
因此在上面,通过调用ccache g++ ... -DPROJECT_NAME=Syren_DLL ...
,当P_VERSION(PROJECT_NAME)
展开时,PROJECT_NAME
被Syren_DLL
取代,从而产生P_VERSION2(Syren_DLL)
,然后导致Syren_DLL
和Versioning
的连接。
- QObject::连接无法将信号连接到*this*对象的插槽
- 打印宏无法连接
- 尝试连接到 TCP 套接字 (Linux) 时连接被拒绝
- 如何在 C 宏中将变量字符串与文字字符串连接起来?
- 如何连接二进制宏值?什么是二进制类型
- 如果 PUB 首先启动并连接到 XPUB/XSUB 代理,则消息将被丢弃,直到 SUB 未连接
- 当条件为真时,有没有办法连接宏参数
- 尝试使用 boost::asio 连接到 SOCKS 5 服务器,但我的连接请求格式不正确
- 即使在派生和添加宏后也无法连接
- 在宏定义 (Clang) 中连接两个字符串
- 如何为连接字符串生成可变宏
- 在C++中连接__FILE__和__LINE__宏
- 无法在宏中连接__LINE__
- libpqxx:如何在连接进程终止后重新连接到Postgresql数据库
- 如何知道连接到QTcpServer的客户端是否已关闭连接
- 在C ++ R3.0.2驱动程序中使用连接池连接到MongoDB副本集的正确方法是什么?
- 为什么字符串连接宏不适用于这种"+"情况?
- 宏连接__FILE和__LINE__与格式化
- 宏字符串连接
- 宏参数连接不像我预期的那样工作