0

I want to change the priority of the preprocessor define process.

see the following code:

#include <iostream>
#include <sstream>

#define $(x)  <<  x  <<  
#define f(x) (#x) 


int main()
{
    auto world = "universe!";

    std::stringstream ss;

    ss <<  f(Hello $(world)) << std::endl;

    std::cout << ss.str();

    return 0;
}

The code run, but the 'f' macro will always processed before the '$' macro.

The current output:

Hello $(world)

Expected output:

Hello universe!

Thx.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
code_by_cr
  • 21
  • 6
  • 1
    is there a "real-world" use case for that or is this only out of interest? – RoQuOTriX Jan 17 '23 at 09:17
  • 1
    it's more interest, otherwise I could use the world var directly in the stringstream. – code_by_cr Jan 17 '23 at 09:22
  • I would advise to stop looking into the preprocessor too much. What do you want to achieve isn't it something that can be done using template functions? Using the preprocessor is not the first thing I would try in C++ . – Pepijn Kramer Jan 17 '23 at 09:26
  • 1
    Does this answer your question? [How, exactly, does the double-stringize trick work?](https://stackoverflow.com/questions/2751870/how-exactly-does-the-double-stringize-trick-work) – Öö Tiib Jan 17 '23 at 09:30
  • https://stackoverflow.com/questions/3419332/c-preprocessor-stringify-the-result-of-a-macro https://stackoverflow.com/questions/2653214/stringification-of-a-macro-value https://stackoverflow.com/questions/21309884/stringify-first-level-macro-expansion-c https://stackoverflow.com/questions/6742501/whats-the-exact-step-of-macro-expanding https://stackoverflow.com/questions/32777514/extra-indirection-in-c-preprocessor-stringification-making-difference https://stackoverflow.com/questions/66164152/force-macro-evaluation-in-c – KamilCuk Jan 17 '23 at 09:31
  • 5
    `'f' macro will always processed before the '$' macro.` I do not understand, if that wouldn't be the case, the output would be `"Hello << world <<"`. `f` is `(#x)` means _everything_ is going to be `#x`, there is no place where `<<` would be removed. The expansion would be `f(Hello $(world))` -> `f(Hello << world <<)` -> `"Hello << world <<"`. – KamilCuk Jan 17 '23 at 09:34
  • Different solution based on parameters: https://godbolt.org/z/dEnTWhdoh – RoQuOTriX Jan 17 '23 at 09:45
  • @KamilCuk that's true, but it's also not the case. – code_by_cr Jan 17 '23 at 09:46

2 Answers2

1

"Solving" the problem:

#include <iostream>
#include <sstream>

#define $(x)  << " " << x   
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define f(x, y) TOSTRING(x) y

int main()
{
    auto world = "universe!";

    std::stringstream ss;

    ss << f(Hello, $(world)) << std::endl;

    std::cout << ss.str();

    return 0;
}

Output:

Hello universe!
RoQuOTriX
  • 2,871
  • 14
  • 25
0

You might "delay" expansion with extra indirection:

#define $(x)  <<  x  <<  
#define STRINGIFY(x) #x
#define f(x) STRINGIFY(x)

but you won't get your expected result but Hello << world << Demo

Without changing your MACRO, you might already get your result by "fixing" your parenthesis (and surrounding):

ss <<  f(Hello) " " $(world) /*<<*/ std::endl;

Demo.

Jarod42
  • 203,559
  • 14
  • 181
  • 302