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

Ash*_*can 2 c c++ c-preprocessor

扩展这个问题这个问题,是否可以使用显示的预处理器方法或包含预处理器符号值的C++多行字符串文字来获得多行字符串文字.例如:

#define SOME_CONSTANT 64

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

理想情况下,我希望将"SOME_CONSTANT"替换为"64".

我尝试过使用我有限的技能组合中的所有技巧,包括字符串化并没有运气.

有任何想法吗?

Sto*_*ica 8

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

令牌替换是迭代发生的.预处理器处理替换,然后返回以查看是否有任何东西可以替换它刚刚替换的序列.我们需要利用它来发挥我们的优势.如果我们有一个假设的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)
});
Run Code Online (Sandbox Code Playgroud)

Live example

我们需要DEFER宏,因为预处理器不会替换它识别为另一个宏的参数的内部.这里的诀窍是,xin DEFER(TO_STRING_)(x)不是宏的参数.所以它被替换为同样的DEFER(TO_STRING_).而我们得到的结果是TO_STRING_(substituted_x).这将成为下一次迭代中的宏调用.因此预处理器将执行TO_STRING_先前替换的替换x.