你能在多行字符串字面值中使用C/C++预处理器标记吗?

3

扩展这个问题这个问题,是否可以使用预处理器方法或包含预处理器符号值的C++多行字符串字面量来创建多行字符串文字?例如:

#define SOME_CONSTANT 64

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

理想情况下,我希望将"SOME_CONSTANT"替换为"64"。
我已经尝试使用我有限的技能集中的所有技巧,包括stringizing,但都没有成功。
有什么想法吗?

你能解释一下你试图解决的实际问题吗?可能有更好的技术不依赖于预处理器技巧。 - R Sahu
1个回答

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)
});

实时演示

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


非常棒的答案。非常感谢,它完美地运行。我将不得不再学习一段时间,以便我理解它被扩展的顺序,但是你的解释很好。 - Ashley Duncan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接