以宏参数给出的先前定义的常量被视为字符串文字

时间:2013-12-10 13:49:16

标签: c++ macros c-preprocessor

假设我已经定义了一个执行此操作的宏

#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”,而我期待“thisIsA-test”。

2 个答案:

答案 0 :(得分:1)

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

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

您的用例:

return  doSomething( stringize_expanded( NAME ) );

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


为什么会这样:

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

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

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

答案 1 :(得分:0)

没有什么可以解决的。

正如您自己所说,破折号在函数名称中无效。

所以,不要使用它们。