Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 615
greenoldman Avatar asked Dec 11 '13 08:12

greenoldman


People also ask

What does ## do in macros?

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.

What does the '#' symbol do in macro expansion?

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.

What is the correct format for naming a macro with multiple 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.

How do I declare macros?

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 .


2 Answers

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.

like image 99
RichardPlunkett Avatar answered Sep 17 '22 10:09

RichardPlunkett


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

like image 25
Cheers and hth. - Alf Avatar answered Sep 21 '22 10:09

Cheers and hth. - Alf