简体   繁体   中英

How to add prefix to macro symbol?

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.

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.

Basics.

The straightforward way is to use preprocessor token pasting , the ## preprocessor operator, as follows:

#define MACRO( s ) L ## s

General solution.

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 eg

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 , eg 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 eg 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>, eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM