以前定义的常量,作为宏参数给出,被认为是字符串文字
A previously defined constant, given as macro argument, is considered as string literal
假设我定义了一个宏来执行
#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
),它不受运算符的约束。
这是使用#
和##
的惯用方法,因为与字面宏名称相比,更需要扩展。在这种情况下,您确实想要##
的默认行为,但如果您想将真正的编程原理应用于该问题,则可以将其视为封装不良的情况(因为接口的名称用于产生输出)。
没有什么可解决的。
正如您自己所说,短划线在函数名中是无效的。
所以,不要使用它们。
相关文章:
- 为什么rand()的使用被认为是不好的
- 为什么 std::shared_ptr 被认为是"heavy"和"expensive",但 std::array "same perfprmance as plain (c-style) arrays
- 一个C头文件可以被认为是一个接口吗
- 为什么const char*和const char[]作为函数参数被认为是等价的
- 为什么12.0==11.999999999999999999被认为是真的
- 这会被认为是糟糕的编程实践吗?
- 如何使用C++中不是文字的变量在数字中显示单引号和两个引号?假设 6'2" 英尺
- 为什么这被认为是恒定的?
- 抽象类/接口中的空方法是否被认为是一种好的做法?
- 如果我具有调用其其他实例之一的超载函数,它是否被认为是递归功能
- std::unique_ptr可以被认为是一个monad吗?
- C++ 指向类的指针和/或引用是否被认为是"movable"?
- 使用自定义宏来简化 cin 和 cout 语句等内容被认为是更好还是更差
- 使用成员函数更改对象或返回并分配它是否被认为是更好的做法?
- 我很难修复我认为是双重免费的东西
- 使用 #define 被认为是"bad practice"吗?
- 是一个被认为是不同类型的班级内部的正向声明
- 这被认为是有效的C 11还是C 14?还是GCC/Clang弄错了
- 以前定义的常量,作为宏参数给出,被认为是字符串文字
- 为什么文字在C++中被认为是表达式