I am looking for general solution to the problem as stated in the title. But as illustration consider my real case. I would like to get wstring
, like this:
L"hello"
but when I have a macro:
#define MACRO(S) ...
and a call:
MACRO("hello") // no L prefix
how to define it to get wstring
, as before?
L S
is treated as 2 symbols.
The double-number-sign or token-pasting operator (##), which is sometimes called the merging or combining operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token, and therefore, can't be the first or last token in the macro definition.
The number-sign or "stringizing" operator (#) converts macro parameters to string literals without expanding the parameter definition. It's used only with macros that take arguments.
To create a macro with arguments, put them in parentheses separated by commas after the macro name, e.g. then BadSquare(3+4) would give 3+4*3+4, which evaluates to 19, which is probably not what we intended.
A macro is a fragment of code that is given a name. You can define a macro in C using the #define preprocessor directive. Here's an example. Here, when we use c in our program, it is replaced with 299792458 .
You need the paste operator, look up # and ## for the pre-processor for exciting new opportunities to both solve problems and create interesting new ones.
http://www.cprogramming.com/reference/preprocessor/token-pasting-operator.html
but for your specific question, try:
#define MACRO(S) L ## S
In my personal experience, the paste operator is one of the best genuine uses for macros in C++ since it gives you something you can't easily do without it. But like most pre-processor features, it is often used for evil.
As a history note, there were early C compilers where you could write #define MACRO(S) L/* */S
which people did, because they legitimately wanted token pasting, but it didnt formally exist. I believe these days the comment hack will explicitly not work in standard complying pre-processors.
The straightforward way is to use preprocessor token pasting, the ##
preprocessor operator, as follows:
#define MACRO( s ) L ## s
You state that you're looking for a "general solution", and the basic token pasting isn't very general.
In particular the straightforward macro gets awkward when you want to define a long string like
L"Blah blah\n"
L"Second line\n"
L"Third line"
You'd then have to write e.g.
MACRO( "Blah blah\n" )
MACRO( "Second line\n" )
MACRO( "Third line" )
Happily you can use C++11 variadic macros to support an arbitrary number of arguments, writing the above literal like this:
MACRO(
"Blah blah\n",
"Second line\n",
"Third line"
)
with MACRO
defined as just, for example,
# define WITH_L_PREFIX_( lit ) L##lit
# define MACRO( ... ) MM_APPLY( WITH_L_PREFIX_, __VA_ARGS__ )
Then the problem is reduced to defining MM_APPLY
, e.g. like this:
#define MM_APPLY( macroname, ... ) \
MM_INVOKE( \
MM_CONCAT( MM_APPLY_, MM_NARGS( __VA_ARGS__ ) ), \
( macroname, __VA_ARGS__ ) \
)
which in turn reduces the problem to defining MM_INVOKE
, MM_CONCAT
, MM_NARGS
, and the more specific MM_APPLY_1
through e.g. MM_APPLY_21
, or whatever your preferred limit on number of arguments is. The reason for this is mainly to support the Visual C++ preprocessor, which isn't quite standard-conforming.
Regarding MM_ARGS
, which produces the number of arguments, see original code by Laurent Deniau, "VA_NARG," 17 January 2006, in the Usenet group <comp.std.c>, e.g. as archived at (https://groups.google.com/forum/?fromgroups=#!topic/comp.std.c/d-6Mj5Lko_s).
For the rest, starting with MM_APPLY_
n, these definitions look like…
#define MM_APPLY_1( macroname, a1 ) \
MM_INVOKE_B( macroname, (a1) )
#define MM_APPLY_2( macroname, a1, a2 ) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_1( macroname, a2 )
#define MM_APPLY_3( macroname, a1, a2, a3 ) \
MM_INVOKE_B( macroname, (a1) ) \
MM_APPLY_2( macroname, a2, a3 )
which, again for reasons of supporting a specific compiler (namely g++ this time) introduces MM_INVOKE_B
.
#define MM_INVOKE( macro, args ) macro args
#define MM_INVOKE_B( macro, args ) macro args // For nested invocation with g++.
MM_CONCAT
is simple,
#define MM_CONCAT__( a, b ) a ## b
#define MM_CONCAT_( a, b ) MM_CONCAT__( a, b )
#define MM_CONCAT( a, b ) MM_CONCAT_( a, b )
And that's that, roughly.
This constitutes a little "macro framework" to apply an operation to each argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With