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;}
)?
Spaces are produced, inside a macro as elsewhere, by space or tab characters, or by end-of-line characters.
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 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.
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.
##
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; }
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.
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