I'm not sure if that's the right terminology to use, however my problem is that the a macro call ("PLUGIN_NAME") as a parameter to another macro call ("IMPLEMENT_MODULE"), which in turn prints it as a string, prints that argument as the macro call ("somePLUGIN_NAME") rather than the expanded result ("someSomePluginName").
Note that "IMPLEMENT_MODULE" is an API call so I can't change that.
#define IMPLEMENT_MODULE(name) something##name
#define PLUGIN_NAME SomePluginName
#define _STR(s) #s
#define STR(s) _STR(s)
#define PLUGIN_NAME_STR STR(PLUGIN_NAME)
int main()
{
string expected = "somethingSomePluginName";
string actual = STR(IMPLEMENT_MODULE(PLUGIN_NAME));
printf("expected: %s || actual: %s\n", expected.c_str(), actual.c_str());
assert(expected == actual);
}
I've put it here:
http://codepad.org/FRzChJtD
You need another helper macro to concatenate the preprocessor tokens after macro-expanding them:
#define IMPLEMENT_MODULE_2(A, B) A##B
#define IMPLEMENT_MODULE(name) IMPLEMENT_MODULE_2(something, name)
See working example here
This technical explanation is that macro expansion will not occur if the token-pasting (##) or stringizing operator (#) are found by the preprocessor.
Related
Having such a simple C++ code:
#include <iostream>
#define NS NS_Static
#define MAKESTRING(x) #x
namespace NS {
int global_x = 8;
void print_global_x() {
std::cout << MAKESTRING(NS) << "::global_x: " << global_x << std::endl;
}
}
I'h expected to get on output NS_Static::global_x: 8 BUT getting just NS::global_x: 8. I've asked a similar question earlier and the user Eljay provided me an answer to use such an extra code:
#define NS Static
#define MAKESTRING_HELPER(x) #x
#define MAKESTRING(x) MAKESTRING_HELPER(x)
It finally works but can someone please explain my why my original approach doesn't work?
Shouldn't the preprocessor (in my original approach) AT FIRST (since it's the first macro defined) run NS NS_Static macro resulting in
NS_Static and then pass that NS_Static to the stringizing MAKESTRING(x) #x macro resulting in expected NS_Static string?
That's how stringizing (#x) in the C preprocessor works.
Unlike normal parameter replacement, the argument is not macro-expanded first.
To get the parameter to macro-expand, add another layer of indirection (a no-op macro like you've discovered, will suffice).
From https://gcc.gnu.org/onlinedocs/cpp/Argument-Prescan.html#Argument-Prescan
Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringized or pasted with other tokens.
In your original function:
#define NS NS_Static
#define MAKESTRING(x) #x
The marco argument is stringized, so NS will not be replaced by NS_Static.
Define two macros, as followed:
#define MACRO_COMBINE_INNER(A,B) A##B
#define MACRO_COMBINE(A,B) MACRO_COMBINE_INNER(A,B)
We use these macros
MACRO_COMBINE_INNER(ABC,__LINE__)
MACRO_COMBINE(ABC,__LINE__)
If the current line number is 123, that's LINE == 123, Why the results expand from the two macros are:
ABC__LINE__
ABC123
Order of expansion plays role here, first the outlier macro is expanded, then inner ones. In first case, after expanding MACRO_COMBINE_INNER you get:
ABC##__LINE__
which turns into ABC__LINE__, because __LINE__ is not a separate token here. In second case, preprocessor expands MACRO_COMBINE(ABC,__LINE__), then
__LINE__ is expanded. `
MACRO_COMBINE_INNER(ABC,123)
And then MACRO_COMBINE_INNER is expanded
ABC##123
There is similar behavior with stringify operator, which requires creating macro like this
#define STRINGIFY(x) #x
#define STRING(x) STRINGIFY(x)
To be able use __LINE__ in string literal:
#define THROW_BAD_INDEX(x) throw std::out_of_range \
(__FILE__ ":" STRING(__LINE__) ": Bad index")
I understand the syntax of #define like,
#define Pi 3.14
So it's obvious that we can use Pi constant instead of 3.14 anywhere in code to make code more readable.
But I encountered a syntax like below.
Does it mean whenever I call the macro
doIT("hello world");
the code statements within {...} will be invoked ?
Does #define allow to give such syntax.?
What does the __FUNCTION__, __VA_ARGS__ mean ?
#define doIT(str, ...) \
{ \
if (pDoLog) pDoLog->LogMsg("[%s] Error: " str, LOG_WRONG, __FUNCTION__, ##__VA_ARGS__); \
printf("[%s] Error: " str "\n", __FUNCTION__, ##__VA_ARGS__); \
}
You don't "call" a macro, and its expansion doesn't get "invoked". The preprocessor just replaces the macro with its expansion, before the code gets compiled.
A macro defined with parentheses such as doIt(str) is a "function-like macro" which means it takes arguments which can be used in the expansion of the macro.
A function-like macro with ... in the argument list indicates it can accept a variable number of arguments. The special predefined symbol __VA_ARGS__ expands to the list of arguments passed to the ... placeholder.
__FUNCTION__ is a special predefined symbol that expands to the name of the current function being compiled, so wherever the macro gets expanded it will use the name of the enclosing function.
I want to create a recursive Macro the will create the "next" class.
Example:
#define PRINTME(indexNum) class m_##(indexNum+1) { }
The indexNum + 1 is evaluated as an int, and won't concatenate to the class name.
How can I cause the compiler to evaluate that, before concatenating?
If you want to generate unique class names every time the PRINTME is invoked then, following is one way:
#define CONCATE1(X,Y) X##Y
#define CONCATE(X,Y) CONCATE1(X,Y)
#define PRINTME class CONCATE(m_,__COUNTER__) {}
__COUNTER__ is an extension in gcc and I am not sure if it's present in other compilers. It's guaranteed that compiler will add 1 every time this macro is invoked.
(In this case, you cannot use __LINE__ or __FILE__ effectively.)
Demo.
The simple answer is that you can't. The preprocessor generally deals in text and tokens; the only place arithmetic is carried out in in #if and #elif directives.
Also, macro expansion isn't recursive. During expansion, the macro being expanded is disabled, and is not available for further substitution.
Well it is doable, based on your motivation and ability to endure ugly code. First off define increment macro:
#define PLUS_ONE(x) PLUS_ONE_##x
#define PLUS_ONE_0 1
#define PLUS_ONE_1 2
#define PLUS_ONE_2 3
#define PLUS_ONE_3 4
#define PLUS_ONE_4 5
#define PLUS_ONE_5 6
#define PLUS_ONE_7 8
#define PLUS_ONE_8 9
#define PLUS_ONE_9 10
// and so on...
You can't just use PLUS_ONE(x) in concatenation operation, since preprocessor won't expand it. There is a way, however - you can abuse the fact that the preprocessor expands variadic arguments.
// pass to variadic macro to expand an argument
#define PRINTME(indexNum) PRINTME_PRIMITIVE(PLUS_ONE(indexNum))
// do concatenation
#define PRINTME_PRIMITIVE(...) class m_ ## __VA_ARGS__ { }
Done!
PRINTME(1); // expands to class m_2 { };
Have you considered using templates instead?
GNU's cpp allows you to turn macro parameters into strings like so
#define STR(x) #x
Then, STR(hi) is substituted with "hi"
But how do you turn a macro (not a macro parameter) into a string?
Say I have a macro CONSTANT with some value e.g.
#define CONSTANT 42
This doesn't work: STR(CONSTANT). This yields "CONSTANT" which is not what we want.
The trick is to define a new macro which calls STR.
#define STR(str) #str
#define STRING(str) STR(str)
Then STRING(CONSTANT) yields "42" as desired.
You need double indirection magic:
#define QUOTE(x) #x
#define STR(x) QUOTE(x)
#define CONSTANT 42
const char * str = STR(CONSTANT);