3

Extending on this question and this question , is it possible to have a multiline string literal using either the preprocessor method shown or C++ multiline string literals that contain the values of a preprocessor symbol. For example:

#define SOME_CONSTANT 64

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

Ideally I want "SOME_CONSTANT" to be replaced with "64".

I have tried using all the tricks in my limited skill set including stringizing and have had no luck.

Any ideas?

Ashley Duncan
  • 825
  • 1
  • 8
  • 22
  • Can you explain the real problem you are trying to solve? There might be better techniques that don't depend on pre-processor tricks. – R Sahu Jun 21 '18 at 05:41

1 Answers1

8

You have two problems. The first is that preprocessor tokens inside quotes (i.e. string literals) aren't substituted. The second is that you must defer the actual stringification until all preprocessing tokens have been replaced. The stringification must be the very last macro that the preprocessor deals with.

Token substitution happens iterativly. The preprocessor deals with the substitution, and then goes back to see if there is anything left to substitute in the sequence it just replaced. We need to use it to our advantage. If we have an hypothetical TO_STRING macro, we need the very next iteration to substitute all preprocessing tokens, and only the one after that to produce a call to the "real" stringification. Fortunately, it's fairly simple to write:

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

Live example

We need the DEFER macro because the preprocessor won't substitute inside something that it recognizes as an argument to another macro. The trick here, is that the x in DEFER(TO_STRING_)(x) is not an argument to a macro. So it's substituted in the same go as DEFER(TO_STRING_). And what we get as a result is TO_STRING_(substituted_x). That becomes a macro invocation in the next iteration. So the preprocessor will perform the substitution dictated by TO_STRING_, on the previously substituted x.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • Awesome answer. Thanks you so much, it works perfectly. I will have to study it for a while longer so I understand the order it is expanded but your explanation is good. – Ashley Duncan Jun 21 '18 at 20:05