以前定义的常量,作为宏参数给出,被认为是字符串文字

A previously defined constant, given as macro argument, is considered as string literal

本文关键字:认为是 文字 字符串 参数 定义 常量      更新时间:2023-10-16

假设我定义了一个宏来执行

#define MY_MACRO(NAME)           
std::string get##NAME() const       
{                               
    return  doSomething(#NAME);             
}

其中doSomething方法签名将类似于此

std::string doSomething(const std::string& parameter);

NAME宏参数中没有破折号时,这种方法效果非常好

例如:

#define MY_MACRO(thisIsA_test) // Works

但是,当我的字符串中有一个破折号时(这种情况可能发生),它将不起作用,因为方法名中不允许使用破折号

#define MY_MACRO(thisIsA-test) // does NOT WORK

我试着用这种方式解决

#define thisIsAtest "thisIsA-test"
#define MY_MACRO(thisIsAtest)

一切都编译得很好,我生成了getthisIsAtest方法,但不幸的是,宏没有被解析,"thisIsAtest"被保留为字符串文字。

换句话说,doSomething参数字符串值将为"thisIsAtest",而我期望的是"thisIA test"。

要展开宏参数,只需使用间接宏。

#define stringize_literal( x ) # x
#define stringize_expanded( x ) stringize_literal( x )

您的用例:

return  doSomething( stringize_expanded( NAME ) );

现在,方法将以宏的名称命名,函数将以宏内容调用。在组织方面有点可疑,但你有它。


为什么有效:

默认情况下,宏参数在被替换之前会展开。因此,如果将thisIsAtest传递给参数NAME,则宏扩展将用"thisIsA-test"替换NAME。但是,当使用预处理器运算符###时,预扩展步骤不适用。

在原始代码中,NAME的一个用法受##约束,另一个受#约束,因此永远不会使用thisIsAtest的宏定义。我刚刚介绍了一个宏stringize_expanded,它引入了NAME的人工使用(通过x),它不受运算符的约束。

这是使用###的惯用方法,因为与字面宏名称相比,更需要扩展。在这种情况下,您确实想要##的默认行为,但如果您想将真正的编程原理应用于该问题,则可以将其视为封装不良的情况(因为接口的名称用于产生输出)。

没有什么可解决的。

正如您自己所说,短划线在函数名中是无效的。

所以,不要使用它们。