假设我已经定义了一个执行此操作的宏
#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”。
答案 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)
没有什么可以解决的。
正如您自己所说,破折号在函数名称中无效。
所以,不要使用它们。