Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Concat Macro argument with namespace

I have a macro, where one of the arguments is an enum value, which is given without specifying the namespace scope. However somewhere inside the macro I need to access it (obviously I must define the namespace there), but I can't seem to concat the namespace name with the template parameter. Given the following samplecode the compiler complains that pasting :: and Val doesnt give a valid preprocessor token (it works fine for concating get and a to getVal though).

 namespace TN
 {
    enum Info
    {
        Val = 0
    };
 }

#define TEST(a) TN::Info get ## a(){return TN::##a;}
TEST(Val)

So is there any way to make this work without using another argument and basically specifying the value to be used twice (e.g. #define TEST(a,b) TN::Info get ## a(){return b;})?

like image 825
Grizzly Avatar asked Dec 18 '09 14:12

Grizzly


People also ask

Can a macro contain spaces?

Spaces are produced, inside a macro as elsewhere, by space or tab characters, or by end-of-line characters.

What is ## in AC macro?

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.

Can you supply more than one argument in a macro call?

The invocation of the macro need not be restricted to a single logical line—it can cross as many lines in the source file as you wish. The number of arguments you give must match the number of parameters in the macro definition.

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.


2 Answers

## is a token pasting operator, i.e. it should make a single token out of multiple bits of token and as the compiler says, ::Val isn't a single token, it's two tokens.

Why do you need think you need the second ## at all? What's wrong with this.

#define TEST(a) TN::Info get ## a () { return TN::a; }
like image 93
CB Bailey Avatar answered Sep 18 '22 09:09

CB Bailey


Only use ## when you want to concatenate two items and have the compiler treat the result as a single token (e.g. an identifier).

In your macro, the first use of ## is correct, as you are trying to construct an identifier by pasting together get and the contents of a, but second use of ## is spurious, as you just want to make an identifier out of the contents of a and the :: operator is a separate entity to that. GCC will complain about this (though MSVC++ copes).

#define TEST(a) TN::Info get ## a(){return TN::a;}

should work.

like image 36
moonshadow Avatar answered Sep 18 '22 09:09

moonshadow