仅使用预处理器进行字符串连接?
Using the only the preprocessor for string concatenation?
是否可以在语言(本例中为 C++)之外连接带引号的字符串文字?
也就是说,我可以定义MY_MACRO(a,b,c)
并这样使用它吗:
MY_MACRO("one", "two", "three")
并将其扩展为:"onetwothree"
?
用例是将属性及其消息应用于函数签名,例如:
MY_ATTRIBUTE_MACRO("this", "is", "the reason") int foo() { return 99; }
它会导致:
[[nodiscard("thisisthe reason")]] int foo() { return 99; }
该语言已经进行了字符串连接!
这个:
"hi" "James"
变成一个字符串文字。
这意味着您根本不需要任何预处理器技巧。
您只需要在宏的输出中使用它:
#define MY_ATTRIBUTE_MACRO(x,y,z) [[nodiscard(x y z)]]
现在这个:
MY_ATTRIBUTE_MACRO("this", "is", "the reason") int foo() { return 99; }
这是:
[[nodiscard("this" "is" "the reason")]] int foo() { return 99; }
这实际上已经是你想要的了,因为隐式字符串连接(发生在 宏扩展之后):
[[nodiscard("thisisthe reason")]] int foo() { return 99; }
[lex.phases]/4:
Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed. If a character sequence that matches the syntax of a universal-character-name is produced by token concatenation, the behavior is undefined. A #include
preprocessing directive causes the named header or source file to be processed from phase 1 through phase 4, recursively. All preprocessing directives are then deleted.
[lex.phases]/6:
Adjacent string literal tokens are concatenated.
我不确定您所说的“语言之外”是什么意思,但是在 C++ 中,任何由空格 仅 分隔的字符串文字都会隐式连接成一个。因此,您的 MY_MACRO
定义实际上 非常 简单:
#include <iostream>
#define MY_MACRO(a, b, c) a b c
int main()
{
std::cout << MY_MACRO("one", "two", "three") << std::endl;
return 0;
}
这个短程序的输出就是你所要求的:onetwothree
。
注意:关于 curiosity/interest,通常建议在定义部分将宏参数括在圆括号中,以避免计算的不良副作用。但是,在这种情况下,使用这样的括号将不起作用,并且会破坏隐式连接:
#define MY_MACRO(a, b, c) (a) (b) (c) // Broken!
是否可以在语言(本例中为 C++)之外连接带引号的字符串文字?
也就是说,我可以定义MY_MACRO(a,b,c)
并这样使用它吗:
MY_MACRO("one", "two", "three")
并将其扩展为:"onetwothree"
?
用例是将属性及其消息应用于函数签名,例如:
MY_ATTRIBUTE_MACRO("this", "is", "the reason") int foo() { return 99; }
它会导致:
[[nodiscard("thisisthe reason")]] int foo() { return 99; }
该语言已经进行了字符串连接!
这个:
"hi" "James"
变成一个字符串文字。
这意味着您根本不需要任何预处理器技巧。
您只需要在宏的输出中使用它:
#define MY_ATTRIBUTE_MACRO(x,y,z) [[nodiscard(x y z)]]
现在这个:
MY_ATTRIBUTE_MACRO("this", "is", "the reason") int foo() { return 99; }
这是:
[[nodiscard("this" "is" "the reason")]] int foo() { return 99; }
这实际上已经是你想要的了,因为隐式字符串连接(发生在 宏扩展之后):
[[nodiscard("thisisthe reason")]] int foo() { return 99; }
[lex.phases]/4:
Preprocessing directives are executed, macro invocations are expanded, and _Pragma unary operator expressions are executed. If a character sequence that matches the syntax of a universal-character-name is produced by token concatenation, the behavior is undefined. A#include
preprocessing directive causes the named header or source file to be processed from phase 1 through phase 4, recursively. All preprocessing directives are then deleted.
[lex.phases]/6:
Adjacent string literal tokens are concatenated.
我不确定您所说的“语言之外”是什么意思,但是在 C++ 中,任何由空格 仅 分隔的字符串文字都会隐式连接成一个。因此,您的 MY_MACRO
定义实际上 非常 简单:
#include <iostream>
#define MY_MACRO(a, b, c) a b c
int main()
{
std::cout << MY_MACRO("one", "two", "three") << std::endl;
return 0;
}
这个短程序的输出就是你所要求的:onetwothree
。
注意:关于 curiosity/interest,通常建议在定义部分将宏参数括在圆括号中,以避免计算的不良副作用。但是,在这种情况下,使用这样的括号将不起作用,并且会破坏隐式连接:
#define MY_MACRO(a, b, c) (a) (b) (c) // Broken!