Stringizing operator in C/C++ - c++

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)

Related

Using define directive to get the namespace name

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.

Visual studio macro __VA_ARGS__ not unpacked correctly

I work on a project, and I need to simulate a recursive macro (here TEST_COLUMN). But it fail on visual 2013.
On gcc, it work correctly, but with visual, I have an error.
So, to debug this macro, I use static_assert (maybe there is a better way).
Each time, in the macros TEST_COLUMN_X(name, ...) the value of name contain ALL the parameters, and not only the first one.
If anyone have an idea to fix this.
Here is the minimal code needed to reproduce it:
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x) //transform x to char
#define EXPAND(x) x
#define NUM_ARGS_HELPER(X,X64,X63,X62,X61,X60,X59,X58,X57,X56,X55,X54,X53,X52,X51,X50,X49,X48,X47,X46,X45,X44,X43,X42,X41,X40,X39,X38,X37,X36,X35,X34,X33,X32,X31,X30,X29,X28,X27,X26,X25,X24,X23,X22,X21,X20,X19,X18,X17,X16,X15,X14,X13,X12,X11,X10,X9,X8,X7,X6,X5,X4,X3,X2,X1,N,...) N
//count to number of argument containing
#define NUM_ARGS(...) EXPAND(NUM_ARGS_HELPER(0, __VA_ARGS__ ,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) in __VA_ARGS__
//define each level of the macro
#define TEST_COLUMN_0 ;
#define TEST_COLUMN_1(name) static_assert(false,"TEST_COLUMN_1 " STR(name));
#define TEST_COLUMN_2(name,...) static_assert(false,"TEST_COLUMN_2 " STR(name)); //TEST_COLUMN_1(__VA_ARGS__)
#define TEST_COLUMN_3(name,...) static_assert(false,"TEST_COLUMN_3 " STR(name)); //TEST_COLUMN_2(__VA_ARGS__)
#define TEST_COLUMN_4(name,...) static_assert(false,"TEST_COLUMN_4 " STR(name)); TEST_COLUMN_3(__VA_ARGS__)
//tricks to call the correct macro (TEST_COLUMN_X)
#define TEST_COLUMN_N1(N,...) TEST_COLUMN_##N(__VA_ARGS__)
#define TEST_COLUMN(N,...) TEST_COLUMN_N1(N,__VA_ARGS__)
//recursive macro
#define TEST_STATIC_COLUMN(...) TEST_COLUMN(NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
int main(int argc, char* argv[])
{
TEST_STATIC_COLUMN(a, b, c);
return 0;
}
Output :
main.cpp(21): error C2338: TEST_COLUMN_3 a, b, c
but it should be
main.cpp(21): error C2338: TEST_COLUMN_3 a
You can test this using the online compiler http://webcompiler.cloudapp.net/
I don't know why, but adding some call to EXPAND solve this issue:
#define TEST_COLUMN_2(name,...) static_assert(false,"TEST_COLUMN_2 " STR(name)); EXPAND(TEST_COLUMN_1(__VA_ARGS__))
#define TEST_COLUMN_3(name,...) static_assert(false,"TEST_COLUMN_3 " STR(name)); EXPAND(TEST_COLUMN_2(__VA_ARGS__))
#define TEST_COLUMN_4(name,...) static_assert(false,"TEST_COLUMN_4 " STR(name)); EXPAND(TEST_COLUMN_3(__VA_ARGS__))
#define TEST_COLUMN_N1(N,...) EXPAND(TEST_COLUMN_##N(__VA_ARGS__))

How to expand macro value to wide string?

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).

Is there a way to concatenate a string to a number without assigning a variable?

I need to have a string that uses a macro value which is an integer. But it's outside of any functions, so I do not want to create a variable. I'm using it in a #pragma comment.
so something like this:
#define num 7
#pragma comment(lib, "string" + num)
which would combine the string and num making it (#pragma comment(lib, "string7")
What you want to do is called stringification:
#define stringify_1(x...) #x
#define stringify(x...) stringify_1(x)
#define NUM 7
char *p = stringify(NUM);
This is inspired by __stringify macro in include/linux/stringify.h in Linux kernel helpers.
I am not completely clear on the intent, it sounds like some preprocessor capability:
http://gcc.gnu.org/onlinedocs/cpp/Stringification.html#Stringification
From that example you find this terse explanation that seems to be what you want.
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
str (foo)
==> "foo"
xstr (foo)
==> xstr (4)
==> str (4)
==> "4"
So you would be able to do something like this:
#define xstr(s) str(s)
#define str(s) #s
#define num 7
#pragma comment(lib, "string" xstr(num))
Normal string merging rules should make that all fine if it were in actual code, but I am not sure if the string will automatically merge in the pragma. That is probably implementation dependent.

How do I turn a macro into a string using cpp?

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);