This question already has answers here:
Creating C macro with ## and __LINE__ (token concatenation with positioning macro)
(3 answers)
Closed 6 years ago.
Consider the following macro:
#define CAT(X, Y) X ## Y
#define CMB(A, B) CAT(A, B)
#define SLB_LOGGING_ALGORITHM CMB(Logging, SLB_ALGORITHM)
where SLB_ALGORITHM is a defined pre-processor symbol.
If I just use CAT directly instead of CMB, SLB_ALGORITHM does not get expanded. Why is that the case and how exactly does the indirection help?
## is a string concatenator, so if you call CAT(Logging, SLB_ALGORITHM) from SLB_LOGGING_ALGORITHM macro, this will result in concatenation of string Logging with string SLB_ALGORITHM, that is: LoggingSLB_ALGORITHM which is likely not what you want.
When calling CMB(Logging, SLB_ALGORITHM) from SLB_LOGGING_ALGORITHM macro, instead, preprocessor first expands Logging and SLB_ALGORITHM (call to CMB()) then concatenate the expanded strings (call to CAT()).
To quote this answer:
When you have a macro replacement, the preprocessor will only expand the macros recursively if neither the stringizing operator # nor the token-pasting operator ## are applied to it.
So the preprocessor does not expand a given macro when ## is applied to it. This is why it is exapnded in the CMB(A, B) level but not when directly using CAT(X, Y) .
Related
So, it's been a while since I have written anything in C++ and now I'm working on a project using C++11 and macros.
I know that by using the stringify operator I can do this:
#define TEXT(a) #a //expands to "a"
How am I supposed to use the preprocessor for recognizing the tokens like + and * to do this:
#define TEXT(a)+ ??? //want to expand to "a+"
#define TEXT(a)* ??? //want to expand to "a*"
when the input has to be in that syntax?
I have tried doing that:
#define + "+"
but of course it doesn't work. How can I make the preprocessor recognize those tokens?
NOTE:
This is actually part of a project for a small language that defines and uses regular expressions, where the resulting string of the macros is to be used in a regex. The syntax is given and we have to use it as it is without making any changes to it.
eg
TEXT(a)+ is to be used to make the regular expression: std::regex("a+")
without changing the fact that TEXT(a) expands to "a"
First,
#define TEXT(a) #a
doesn't “convert to "a"”. a is just a name for a parameter. The macro expands to a string that contains whatever TEXT was called with. So TEXT(42 + rand()) will expand to "42 + rand()". Note that, if you pass a macro as parameter, the macro will not be expanded. TEXT(EXIT_SUCCESS) will expand to "EXIT_SUCCESS", not "0". If you want full expansion, add an additional layer of indirection and pass the argument to TEXT to another macro TEXT_R that does the stringification.
#define TEXT_R(STUFF) # STUFF
#define TEXT(STUFF) TEXT_R(STUFF)
Second, I'm not quite sure what you mean with TEXT(a)+ and TEXT(a)*. Do you want, say, TEXT(foo) to expand to "foo+"? I think the simplest solution in this case would be to use the implicit string literal concatenation.
#define TEXT_PLUS(STUFF) # STUFF "+"
#define TEXT_STAR(STUFF) # STUFF "*"
Or, if you want full expansion.
#define TEXT_R(STUFF) # STUFF
#define TEXT_PLUS(STUFF) TEXT_R(STUFF+)
#define TEXT_STAR(STUFF) TEXT_R(STUFF*)
Your assignment is impossible to solve in C++. You either misunderstood something or there’s an error in the project specification. At any rate, we’ve got a problem here:
TEXT(a)+ is to be used to make the regular expression: std::regex("a+") without changing the fact that TEXT(a) expands to "a" [my emphasis]
TEXT(a) expands to "a" — meaning, we can just replace TEXT(a) everywhere in your example; after all, that’s exactly what the preprocessor does. In other words, you want the compiler to transform this C++ code
"a"+
into
std::regex("a+")
And that’s simply impossible, because the C++ preprocess does not allow expanding the + token.
The best we can do in C++ is use operator overloading to generate the desired code. However, there are two obstacles:
You can only overload operators on custom types, and "a" isn’t a custom type; its type is char const[2] (why 2? Null termination!).
Postfix-+ is not a valid C++ operator and cannot be overloaded.
If your assignment had just been a little different, it would work. In fact, if your assignment had said that TEXT(a)++ should produce the desired result, and that you are allowed to change the definition of TEXT to output something other than "a", then we’d be in business:
#include <string>
#include <regex>
#define TEXT(a) my_regex_token(#a)
struct my_regex_token {
std::string value;
my_regex_token(std::string value) : value{value} {}
// Implicit conversion to `std::regex` — to be handled with care.
operator std::regex() const {
return std::regex{value};
}
// Operators
my_regex_token operator ++(int) const {
return my_regex_token{value + "+"};
}
// more operators …
};
int main() {
std::regex x = TEXT(a)++;
}
You don't want to jab characters onto the end of macros.
Maybe you simply want something like this:
#define TEXT(a, b) #a #b
that way TEXT(a, +) gets expanded to "a" "+" and TEXT(a, *) to "a" "*"
If you need that exact syntax, then use a helper macro, like:
#define TEXT(a) #a
#define ADDTEXT(x, y) TEXT(x ## y)
that way, ADDTEXT(a, +) gets expanded to "a+" and ADDTEXT(a, *) gets expanded to "a*"
You can do it this way too:
#define TEXT(a) "+" // "a" "+" -> "a+"
#define TEXT(a) "*" // "a" "*" -> "a*"
Two string literals in C/C++ will be joined into single literal by specification.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to convert concatenated strings to wide-char with the C preprocessor?
I have a string literal defined using a #define:
#define B "1234\0"
How do I use this definition to get this wide string literal at compile time?:
L"1234\0"
(just the #defined string literal with L prepended to make it into a wide string).
I tried this:
#define MAKEWIDE(s) L##s
but this generates LB.
Token pasting needs an additional level of indirection to deal properly with macros used as operands. Try something like:
#define PASTE(x, y) x##y
#define MAKEWIDE(x) PASTE(L,x)
This will work just fine:
#define B "1234\0"
#define LB L"" B
No comma is allowed in a macro argument because it will be treated as more than one arguments and the preprocessing will be wrong. However, we can parenthesize the argument to let preprocessor treat it as one argument. Is there a macro or other techniques which can remove the enclosing parentheses?
For example, if I define a macro like
#define MY_MACRO(a, b) ...
and use it like
MY_MACRO( A<int, double>, text );
will be wrong. use it like
MY_MACRO( (A<int, double>), text)
with a macro or technique to remove the parentheses will be fine. Boost provides BOOST_IDENTITY_TYPE macro for only types but not general cases
#define ESC(...) __VA_ARGS__
then
MY_MACRO( ESC(A<int, double>), text );
might do what you want.
This macro trick is similar to Yakk's solution but removes the need to explicitly pass in another macro as a parameter.
#include <stdio.h>
#define _Args(...) __VA_ARGS__
#define STRIP_PARENS(X) X
#define PASS_PARAMETERS(X) STRIP_PARENS( _Args X )
int main()
{
printf("without macro %d %d %d %d %d %d\n", (5,6,7,8,9,10) ); // This actually compiles, but it's WRONG
printf("with macro %d %d %d %d %d %d\n", PASS_PARAMETERS((5,6,7,8,9,10)) ); //Parameter "pack" enclosed in parenthesis
return 0;
}
Of course you could get creative by making the PASS_PARAMETERS macro into a variadic macro and pass in multiple parameter packs.
Only maybe removing parentheses:
If you need to strip one layer of parenthesis, but only if there are parenthesis to strip, this longer set of macros does the trick:
#define DEPAREN(X) ESC(ISH X)
#define ISH(...) ISH __VA_ARGS__
#define ESC(...) ESC_(__VA_ARGS__)
#define ESC_(...) VAN ## __VA_ARGS__
#define VANISH
This may be needed if you want to use MY_MACRO for different sets of datatypes:
#define MY_MACRO(a, b) DEPAREN(a), b
MY_MACRO( ({x, y, z}), text )
//> {x,y,z}, text
MY_MACRO( singlearg, text )
//> singlearg, text
How it works:
We start with DEPAREN(X) ESC(ISH X). If X has parenthesis, we get ESC(ISH(X)). If X does not have parenthesis, we get ESC(ISH X).
We then expand ESC(...) into ESC_(__VA_ARGS__), which expands the interior.
ISH(...) turns into ISH __VA_ARGS__, which strips one layer of parentheses from X. Now, regardless of whether or not X originally had parenthesis, we have ESC_(ISH X).
We now need to get rid of ISH. However, because we already defined ISH(...), we can't also define it as #define ISH . That's why we concatenate it with another token (VAN) to get VANISH X.
VANISH is defined as , so we are finally left with X, sans parentheses.
A simple hack could be to use variadic macros:
#define MY_MACRO(a, b...) ...
Then you can use it like:
MY_MACRO(text, A<int, double>)
The comma in the second argument is still interpreted as the argument separator (meaning the macro is actually called with three arguments), but it's expanded inside the macro, making the behavior the same. The variadic argument has to be last in the macro, however.
This question already has answers here:
What are the applications of the ## preprocessor operator and gotchas to consider?
(13 answers)
The ## operator in C
(7 answers)
Closed 9 years ago.
What's the meaning of "##" in the following?
#define CC_SYNTHESIZE(varType, varName, funName)\
protected: varType varName;\
public: inline varType get##funName(void) const { return varName; }\
public: inline void set##funName(varType var){ varName = var; }
The operator ## concatenates two arguments leaving no blank spaces between them:
e.g.
#define glue(a,b) a ## b
glue(c,out) << "test";
This would also be translated into:
cout << "test";
It concatenates tokens without leaving blanks between them. Basically, if you didn't have the ## there
public: inline varType getfunName(void) const { return varName; }\
the precompiler would not replace funName with the parameter value. With ##, get and funName are separate tokens, which means the precompiler can replace funName and then concatenate the results.
This is called token pasting or token concatenation.
The ## (double number sign) operator concatenates two tokens in a macro invocation (text and/or arguments) given in a macro definition.
Take a look here at the official GNU GCC compiler documentation for more information.
I have a macro defined in C something like this:
#define SOME_FIELD(_A_,_B_,_C_) \
MyObj[ ## _A_ ## ].somePTR = \
(DWORD_PTR) (buff_ ## _C_ ## _C_ ## _ ## _B_ ## );
What i can understand that for index A we are getting some value for "somePTR". My question is, What is ## <name> ## notation for and with this how value of somePTR is calculated??
I am new to such a macro so a descriptive explanation would be very helpful.
That is called token concatenation. It allows you to glue arguments together.
For your example, SOME_FIELD(Param1,Param2,Param3); expands like this:
MyObj[Param1].somePTR = (DWORD_PTR) (buff_Param3Param3_Param2);
It's easy enough to try this out yourself by using your compiler's pre-processor. You don't generally need to go to the trouble of writing a fully-fledged C program—the pre-processor can generally be invoked by itself.
That's preprocessor token pasting
http://msdn.microsoft.com/en-us/library/09dwwt6y(v=vs.80).aspx
It will copy the actual parameter token as a string literal, so read it like
// preprocessor_token_pasting.cpp
#include <stdio.h>
#define paster( n ) printf_s( "token" #n " = %d", token##n )
int token9 = 9;
int main()
{
paster(9);
}
the ## is concatenation primitive, it's used to create nwe symbols.
It's useful to create names in macro:
#define GENERIC_GETTER(f,g) (g->member_ ## f )
GENERIC_GETTER(a,b) will create (b->member_a) (new symbol created). If you don't use sharp-sharp, it would create (b->member_ a) (not glued together)
Normally, the ## operator concatenates two tokens: it requires a legal
token on the left and a legal token on the right, and results in a new
token. In your case, the first line in the macro
(MyObj[ ## _A_ ## ].somePtr = \) is
illegal, and results in undefined behavior. Most implementations just
concatenate the strings, then retokenize once they've finished all of
the substitutions, so it will work, but it's not guaranteed. And as far
as I can tell here, it's not necessary. In the second line, on the
other hand, you are generating a new token. If you invoke the macro:
SOME_FIELD(x,y,z);
it will expand to:
MyObj[x].somePtr = (DWORD_PTR)(buff_zzy);
(I might add that the use of symbols like _A_, _B_ and _C_ is also
undefined behavior. A symbol starting with an underscore followed by a
capital letter is in the namespace of the implementation.)