Search code examples
c++c-preprocessorpreprocessor

Using the only the preprocessor for string concatenation?


Is it possible to concatenate quoted string literals outside of the language (C++, in this case)?

That is, can I define MY_MACRO(a,b,c) and use it thus:

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

and have it expand to: "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; }

Solution

  • 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:

    [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.

    Translation phase 6:

    [lex.phases]/6: Adjacent string literal tokens are concatenated.