简体   繁体   English

使用唯一的预处理器进行字符串连接?

[英]Using the only the preprocessor for string concatenation?

Is it possible to concatenate quoted string literals outside of the language (C++, in this case)?是否可以连接语言之外的带引号的字符串文字(在本例中为 C++)?

That is, can I define MY_MACRO(a,b,c) and use it thus:也就是说,我可以定义MY_MACRO(a,b,c)并使用它:

MY_MACRO("one", "two", "three")

and have it expand to: "onetwothree" ?并将其扩展为: "onetwothree"

The use case is to apply an attribute and its message to, say, a function signature, like so:用例是将属性及其消息应用于函数签名,如下所示:

MY_ATTRIBUTE_MACRO("this", "is", "the reason") int foo() { return 99; }

and it would result in:这将导致:

[[nodiscard("thisisthe reason")]] int foo() { return 99; }

The language already does string concatenation!该语言已经进行了字符串连接!

This:这个:

"hi" "James"

becomes just one string literal.变成只是一个字符串文字。

That means you do not need any preprocessor tricks for this at all.这意味着您根本不需要任何预处理器技巧。


You need only employ this in the output of your macro:您只需要在宏的输出中使用它:

#define MY_ATTRIBUTE_MACRO(x,y,z) [[nodiscard(x y z)]]

Now this:现在这个:

MY_ATTRIBUTE_MACRO("this", "is", "the reason") int foo() { return 99; }

is this:这是:

[[nodiscard("this" "is" "the reason")]] int foo() { return 99; }

which is actually already what you wanted, because of the implicit string concatenation (which happens after macro expansion):这实际上已经是您想要的,因为隐式字符串连接(发生宏扩展之后):

[[nodiscard("thisisthe reason")]] int foo() { return 99; }

Translation phase 4 :翻译阶段4

[lex.phases]/4: Preprocessing directives are executed, macro invocations are expanded , and _Pragma unary operator expressions are executed. [lex.phases]/4:执行预处理指令,扩展宏调用,并执行_Pragma 一元运算符表达式。 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. #include预处理指令使指定的头文件或源文件从阶段 1 到阶段 4 以递归方式进行处理。 All preprocessing directives are then deleted.然后删除所有预处理指令。

Translation phase 6 :翻译阶段6

[lex.phases]/6: Adjacent string literal tokens are concatenated. [lex.phases]/6:相邻的字符串文字标记。

I'm not sure what you mean by "outside the language" but, in C++, any string literals separated just by whitespace are implicitly concatenated into one.我不确定您所说的“语言之外”是什么意思,但是在 C++ 中,任何由空格分隔的字符串文字都会隐式连接为一个。 Thus, your MY_MACRO definition is actually very simple:因此,您的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;
}

The output from this short program is what you asked for: onetwothree .这个简短程序的输出是您所要求的: onetwothree


Note: As a matter of curiosity/interest, it is normally recommended to enclose macro arguments in parentheses, in the definition part, so as to avoid unwanted side effects of the evaluation.注意:出于好奇/兴趣,通常建议将宏参数括在括号中,在定义部分,以避免评估的不必要的副作用。 However, in this case, using such parentheses won't work, and breaks the implicit concatenation:但是,在这种情况下,使用这样的括号将不起作用,并且会破坏隐式连接:

#define MY_MACRO(a, b, c) (a) (b) (c) // Broken!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM