您可以在多行字符串文字中使用C / C ++预处理程序令牌吗

时间:2018-06-21 05:26:03

标签: c++ c c-preprocessor

this questionthis question上进行扩展,可以使用所示的预处理器方法或包含预处理器符号值的C ++多行字符串文字来获得多行字符串文字。例如:

#define SOME_CONSTANT 64

#define QUOTE(...) #__VA_ARGS__
const char * aString = QUOTE(
{
    "key":"fred",
    "value":"SOME_CONSTANT"
}
);

理想情况下,我希望将“ SOME_CONSTANT”替换为“ 64”。

我尝试使用有限技能中的所有技巧,包括stringizing,但没有运气。

有什么想法吗?

1 个答案:

答案 0 :(得分:7)

您有两个问题。首先是引号(即字符串文字)内的预处理器标记不会被替换。第二个是您必须推迟实际的字符串化,直到所有预处理标记都已被替换。字符串化必须是预处理器处理的最后一个宏。

令牌替换迭代进行。预处理器处理替换,然后返回以查看是否有任何东西可以按其替换的顺序进行替换。我们需要利用它来发挥我们的优势。如果我们有一个假想的TO_STRING宏,则需要进行下一次迭代以替换所有预处理标记,然后仅 一个后继标记来生成对“真实”字符串化的调用。幸运的是,编写起来非常简单:

#define TO_STRING(...) DEFER(TO_STRING_)(__VA_ARGS__)
#define DEFER(x) x
#define TO_STRING_(...) #__VA_ARGS__

#define SOME_CONSTANT 64

#define QUOTE(...) TO_STRING(__VA_ARGS__)
const char * aString = QUOTE({
    "key":"fred",
    "value": TO_STRING(SOME_CONSTANT)
});

Live example

我们需要DEFER宏,因为预处理器不会在它可以识别为另一个宏的参数的内部进行替换。这里的技巧是x中的DEFER(TO_STRING_)(x)不是宏的参数。因此,它与DEFER(TO_STRING_)相同。结果是TO_STRING_(substituted_x)。这将在下一次迭代中成为宏调用。因此,预处理器将对先前替换的TO_STRING_执行x指示的替换。