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);
Related
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 need to call a function which call a macro-function to change macro-value in runtime.
This code isn't compiled:
#define MY_MACRO 32
#define SET_MY_MACRO_VAL(IS_TRUE)(MY_MACRO=(IS_TRUE)?16:U32)
In function SET_MY_MACRO_VAL
> error: lvalue required as left operand of assignment
#define SET_MY_MACRO_VAL(IS_TRUE)(MY_MACRO=(IS_TRUE)?16:U32)
^
in expansion of macro 'SET_MY_MACRO_VAL'
SET_MY_MACRO_VAL(True);
^
Macro value are replaced BEFORE compile time by the preprocessor and do not exist at run time.
It is not a variable it is simply a way of using text for the value "32".
If you do this :
#define MY_MACRO 32
#define SET_MY_MACRO_VAL(IS_TRUE)(MY_MACRO=(IS_TRUE)?16:U32)
It will be expanded to this
#define MY_MACRO 32
#define SET_MY_MACRO_VAL(IS_TRUE)(32=(IS_TRUE)?16:U32)
What you can do is use a #define
#ifdef SET_MACRO_VAL_32
#define MY_MACRO 32
#else
#define MY_MACRO 16
#endif
Or use a conditionnal macro if you prefer
#if (IS_TRUE>0)
#define MY_MACRO 32
#else
#define MY_MACRO 16
#endif
Edit :
In C++, you shouldn't really need macro though. You can use template and / or constexpr variable for compile-time value. In C++17 you can even use constexpr if.
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.
Let's say I have a macro
#define CLASS_NAME ItemsList
Later I would like to use the value of it, not as a symbol, but as wide string. And my problems begin. When I simply write (in a regular C++ code, not in macro definition):
L#CLASS_NAME
compiler gives me an error, saying token # was not expected here. When I write proxy for it
#define WSTRING(S) L#S
and use it
WSTRING(CLASS_NAME)
I will get wide string with content "CLASS_NAME". I would like to expand macro, meaning getting its value, not converting the macro name.
So how to do it properly (Visual Studio 2012)?
If you want L"ItemsList" then you can use:
#define CONCAT2(X, Y) X##Y
#define CONCAT(X, Y) CONCAT2(X, Y)
#define STRINGIFY2(X) #X
#define STRINGIFY(X) STRINGIFY2(X)
#define WIDEN(X) CONCAT(L, STRINGIFY(X))
And then write WIDEN(CLASS_NAME).
I am trying to use the stringizing operator #, but I get the error stray ‘#’ in program. Here is how I am using it.
#define STR "SOME_STRING"
#define BM 8
#define NUM_OF_THREADS 8
#define VER_STR (STR #BM #NUM_THREADS)
I expect to get SOME_STRING88 for VER_STR but instead get an error. What mistake am I doing?
You need to turn the numerical constants into a string. However, #BM is an error, since the syntax is only valid for macro parameters.
So you need to force en expansion through an intermediate macro. And you may as well have a STRINGIFY macro to do it:
#include <iostream>
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
#define STR "SOME_STRING"
#define BM 8
#define S_BM STRINGIFY(BM)
#define NUM_OF_THREADS 8
#define S_NUM_OF_THREADS STRINGIFY(NUM_OF_THREADS)
#define VER_STR STR S_BM S_NUM_OF_THREADS
int main() {
// your code goes here
std::cout << VER_STR;
return 0;
}
You can see the above in action at http://ideone.com/cR1KZP
EDIT
As Magnus Hoff pointed out, you can invoke STRINGIFY directly as well:
#define VER_STR STR STRINGIFY(BM) STRINGIFY(NUM_OF_THREADS)