Escaping a # symbol in a #define macro?
Solution 1
As far as I remember you cannot use another preprocessor directive in define.
Solution 2
It is possible to insert a hash token into the preprocessed token stream. You can do it as follows:
#define MACRO(hash, name) hash include name
MACRO(#,"hello")
—expands to:
# include "hello"
However, the standard explicitly rules out any further analysis of such line for the existence of preprocessing directives [cpp.rescan]:
The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one.
Solution 3
The problem isn't actually getting a # symbol in the output of your preprocessor.
Apparently you want the preprocessor to reparse your file, to deal with newly created #include directives as part of macro expansion. It doesn't work that way. If a line starts with #, it's an instruction for the preprocessor and interpreted. If a line doesn't start with #, it's only subject to preprocessor transformation including macro substitution. This is a once-per-line test.
MACRO(Test)
does not start with #. Therefore it is not interpreted as a preprocessor directive; instead it's subject to macro replacement rules.
Solution 4
This is because the # has special meaning when used in a macro.
# means quote the following token (which should be a macro parameter name)
## means concatenate the preceding and following tokens.
In your situation the # is not followed by a proper token. So in your situation we need to go through a level of indirection:
#define QUOTE(name) #name
#define TEST(name) QUOTE(name ## foo)
#include TEST(scot)
Solution 5
You can't do that. Preprocessor directives are recognized before macro expansion; if the macro expands into something that looks like a preprocessor directive, that directive will not be recognized. The best you can do is create a macro for the file name:
#define MACRO(name) "name##foo"
...
#include MACRO(Test)
Rob
C++, MFC, Win32, WTL, STL, Boost, HTML, CSS, JavaScript, Qt, Python, jQuery Mobile.
Updated on July 09, 2022Comments
-
Rob almost 2 years
Without going into the gory details I want to use a
#define
macro that will expand to a#include
but the '#' sign is confusing the preprocessor (as it thinks I want to quote an argument.)For example, I want to do something like this:
#define MACRO(name) #include "name##foo"
And use it thus:
MACRO(Test)
Which will expand to:
#include "Testfoo"
The humble # sign is causing the preprocessor to barf. MinGW gives me the following error:
'#' is not followed by a macro parameter
I guess I need to escape the # sign but I don't if this is even possible.
Yes, macros are indeed evil...
-
EFraim almost 15 yearsUse
<>
instead of""
.""
Are not interpolated. -
polyglot almost 15 yearsClearest answer on here I think - effectively he's asking for a 2nd parse of the preprocessor, well noted.
-
Rob almost 15 yearsThanks. I found a better way to achieve what I was after in the end, without using macros.
-
pbean over 14 yearsIt would have been nice if you mentioned in which way you achieved what you wanted? :-)
-
Marius over 14 yearsthat will not allow for the case when you want to replace it with two #includes, or perhaps eliminate them altogether. But it's perhaps the best option.
-
Jonathan Leffler over 9 yearsBut the output of this is not a
#include
directive (it is just a line that contains#include
); you can't generate preprocessor directives like that. You also haven't really explained whatBOOST_PP_CAT
is and where you get it from. -
Jonathan Leffler over 9 yearsNote that a modern preprocessor won't expand the
name
inside the quotes; this will end up as#include "name##foo"
regardless of the value passed to the macro. -
Jonathan Leffler over 9 yearsThis works for the question, where the name to be included doesn't need
.h
appended. It is harder to make it work in a scenario where you have#include USR_HEADER(name)
in the code, and you want it to become#include "name.h"
for C or#include "cname"
for C++. That's because token pasting doesn't work when one of the tokens is.h
and because string concatenation occurs after the preprocessor is finished (so generating#include "name" ".h"
leaves you with an invalid preprocessor directive). I'm not yet sure how to solve that, orSTD_HEADER(stdio)
for<stdio.h>
or<cstdio>
. -
xryl669 about 8 yearsYou can use also
#define MACRO(name) #name "foo"
that simply rely on string concatenation done when 2 strings are following on a single statement. -
masterxilo over 7 years@JonathanLeffler To be fair, if you google
BOOST_PP_CAT
you find only information on the macro that he meant. And the name is long enough to consider this a GUID ;) -
Jonathan Leffler over 7 years@xryl669: Note that adjacent string literal concatenation is done in Phase 6 of the translation process, but the preprocessor finishes in Phase 4. Thus, the
#define MACRO(name) #name "foo"
won't help; it will generate two separate strings which is not a valid header name. -
Jonathan Leffler over 7 yearsThis answer doesn't seem to be related to the question, which is really asking about how to generate a file name for use with
#include
.