I want to change the priority of the preprocessor define process.
see the following code:
#include <iostream>
#include <sstream>
#define $(x) << x <<
#define f(x) (#x)
int main()
{
auto world = "universe!";
std::stringstream ss;
ss << f(Hello $(world)) << std::endl;
std::cout << ss.str();
return 0;
}
The code run, but the 'f' macro will always processed before the '$' macro.
The current output:
Hello $(world)
Expected output:
Hello universe!
Thx.
"Solving" the problem:
#include <iostream>
#include <sstream>
#define $(x) << " " << x
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define f(x, y) TOSTRING(x) y
int main()
{
auto world = "universe!";
std::stringstream ss;
ss << f(Hello, $(world)) << std::endl;
std::cout << ss.str();
return 0;
}
Output:
Hello universe!
You might "delay" expansion with extra indirection:
#define $(x) << x <<
#define STRINGIFY(x) #x
#define f(x) STRINGIFY(x)
but you won't get your expected result but Hello << world << Demo
Without changing your MACRO, you might already get your result by "fixing" your parenthesis (and surrounding):
ss << f(Hello) " " $(world) /*<<*/ std::endl;
Demo.
I've made some variadic output macros, especially for test output purposes.
Examples: C++-code // output: function file(first and last char) linenumber variable=value
L(i,b); // result e.g. {evenRCpower#ih2943: i=36 b=1 #}
L(hex,pd,dec,check.back(),even,"e.g.");
// result e.g.: {way#ih3012: pd=babbbaba check.back()=15216868001 even=1 e.g. #}
They are working fine, having some minor restrictions, which can be lowered by more text analysis (restricted usage of comma and output specifications).
Up to now, they are working at least under g++1z and c++1z.
My questions:
Main question: How to get the macro completely thread safe?
Is there a solution needing no textual analysis, e.g. to avoid #VA_ARGS and get the names for every parameter separated?
How to distinguish parameters from output manipulators (necessary)?
What's to change for other (newer) C++ and g++ versions?
Even to write one complete line into one local string using a locally defined outstream isn't completely solving the problem of output mixing in parallel work - but why? In which C++ version this problem will be solved?
I'll give a simplified base version with use of "std::out" will work fine, but of course give bad results, when used in parallel threads:
#define WO_IS 1
#define L(...) locate(__FILE__,__LINE__,__func__,"\n{",": "," #}\n",#__VA_ARGS__,##__VA_ARGS__)
string argTExcludes = " hex dec std::hex std::dec ", funcExcludes = " setprecision ";
string argT(const string sarg,int &nextpos) { // NO exact analysis!! Simple strings and chars allowed, but parameters with commata like in f(x,y,"A,",','): crazy output !!
int i = nextpos+1, pos = i, follow = 0; string nom; bool apo = false;
for (; i < sarg.size(); i++)
if(sarg.at(i) == ' ') { ;
} else if ((sarg.at(i) == ',')||(i == (sarg.size()-1))) {
nom = sarg.substr(pos,i-pos);
if (argTExcludes.find(nom) != std::string::npos) { nextpos = i; return ""; };
break;
} else {
if ((sarg.at(i) != ' ') && (!follow++) && ((sarg.at(i) == '"')||(sarg.at(i) == '\'')) ) apo = true;
if ((sarg.at(i) == '"') && ( (i==0)||((i > 0) && (sarg.at(i-1) != '\'')) )) { i++; while ((sarg.at(i) != '"') && (i < sarg.size())) i++; };
if (sarg.at(i) == '(') {
nom = sarg.substr(pos,i-pos); if (funcExcludes.find(nom) != std::string::npos) apo = true;
};
};
nextpos = i;
return (apo)?"":sarg.substr(pos,i-pos)+"=";
};
template <typename... Ts>
inline void locate(string ort,long line,string funct,const string prefix, const string trenner, const string postfix, string sarg, Ts... args)
{
#if WO_IS > 0 // all range restrictions abandoned
int pos = -1; bool apo; sarg += ",";
std::ios_base::fmtflags f( cout.flags() );
std::cout << prefix << funct << '#' << ort[0] << ort.back() << dec << line << trenner;
cout.flags( f );
((std::cout << argT(sarg,pos) << args << ' '), ...); // forbidden: endl - it will give syntax error even when no blank at end
// ((std::cout << argT(sarg,pos); std::cout << args; std::cout << ' '), ...); // forbidden: endl - it will also give syntax error
if (postfix == "\0") std::cout.flush();
else std::cout << postfix; // << endl;
#endif
};
Is there a solution needing no textual analysis, e.g. to avoid #VA_ARGS and get the names for every parameter separated?
You might do it with hard coded limit.
Some utilities MACRO to "iterate" over __VA_ARGS__:
#define COUNT_VA_ARGS(...) TAKE_10(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define TAKE_10(_1, _2, _3, _4, _5, _6, _7, _8, _9, N,...) N
#define JOIN(a, b) JOIN_H(a, b)
#define JOIN_H(a, b) a ## b
#define WRAP_VA_ARGS_0(wrap)
#define WRAP_VA_ARGS_1(wrap, x0) wrap(x0)
#define WRAP_VA_ARGS_2(wrap, x0, x1) wrap(x0), wrap(x1)
#define WRAP_VA_ARGS_3(wrap, x0, x1, x2) wrap(x0), wrap(x1), wrap(x2)
#define WRAP_VA_ARGS_4(wrap, x0, x1, x2, x3) wrap(x0), wrap(x1), wrap(x2), wrap(x3)
#define WRAP_VA_ARGS_5(wrap, x0, x1, x2, x3, x4) wrap(x0), wrap(x1), wrap(x2), wrap(x3), wrap(x4)
// ...
// Call into one of the concrete ones above
#define WRAP_VA_ARGS(wrap, ...) JOIN(WRAP_VA_ARGS_, COUNT_VA_ARGS(__VA_ARGS__))(wrap, __VA_ARGS__)
Then, you might do something like
template <typename... Ts>
void print(std::source_location loc, const Ts&...args)
{
std::cout << loc.function_name() << ":" << loc.line() << std::endl;
((std::cout << args << " "), ...) << std::endl;
}
#define NAMED_PAIR(x) #x, x
#define PRINT(...) print(std::source_location::current(), WRAP_VA_ARGS(NAMED_PAIR, __VA_ARGS__))
Demo
I was trying the below program
#include <iostream>
using namespace std;
#define MKSTR(x) #x
#define CONCATE( x , y ) (x)##(y)
int main()
{
int xy = 100;
cout << MKSTR(HELLO C++) << endl;
cout << CONCATE(HELLO,C++) << endl;
cout << CONCATE(x,y) << endl;
return 0;
}
and getting the error
error C2065: 'HELLO' : undeclared identifier
. I don't see see why the VS 2012 compiler is expecting the macro argument or is treating them as identifier. Also the MKSTR macro worked fine but the CONCATE macro is giving me trouble. Can't understand why compiler is doing so.
You need to concatenate symbols first, and then expand it in a string, like this (compiles in GCC 4.8.1) :
#include <iostream>
using namespace std;
#define MKSTR(x) #x
#define CONCATE( x , y ) x ## y
#define CONCATESTR( x , y ) MKSTR(x ## y)
int main()
{
int xy = 100;
cout << MKSTR(HELLO C++) << endl;
cout << CONCATESTR(HELLO,C++) << endl;
cout << CONCATE(x,y) << endl;
return 0;
}
output :
HELLO C++
HELLOC++
100
EDIT :
So for the question of why MKSTR(CONCAT(...)) is not working, the reason is because of the expansion order of macros.
Because CONCAT is a parameter of MKSTR and MKSTR uses operator #, the argument is not expanded but instead immediately stringified. You could do this instead to make it work :
#include <iostream>
using namespace std;
#define CONCATE( x , y ) x ## y
#define MKSTR(x) #x
#define MKSTR2(x) MKSTR(x)
#define CONCATESTR( x , y ) MKSTR(x ## y)
int main()
{
int xy = 100;
cout << MKSTR2(HELLO C++) << endl;
cout << MKSTR2(CONCATE(HELLO,C++)) << endl;
cout << CONCATE(x,y) << endl;
return 0;
}
and it will output what you expect.
I want to dynamically create strings using MACRO. e.g. if I have int i in range of 1:n and string "testArray". I should be able to create testArray[0],testArray[1], ... testarray[n-1]
Please let me know if it is possible.
Below is sample code :
void fun2(int x,std::string name)
{
/*do something*/
}
void fun1()
{
for (unsigned int i = 0 ;i < 5 ; ++i )
{
// I want to create a MACRO such that it create "testArray[0]","testArray[1]",..."testArray[4]" etc.
fun2(x,CREATE_ARRAY_ELEM ("testArray",i));
}
}
I tried below but it does not work :
#define STR1(x) #x
#define CREATE_INDEX(paramName,elementIndex) #paramName << "[" << elementIndex << "]"
#define CREATE_ARRAY_ELEM(paramName,elementIndex) CREATE_INDEX(paramName,elementIndex)
#define STRINGIZE_1(x) STR1(x)
You appear to be wanting to create the string literals "testArray[0]", "testArray[1]", etc.. at compile time. Thats not going to happen. You could easily accomplish this at runtime using an ostringstream, but I don't think that is what you're looking for.
If it is what you're looking for, then...
#include <iostream>
#include <sstream>
using namespace std;
static std::string array_str(const char* s, unsigned int i)
{
std::ostringstream oss;
oss << s << '[' << i << ']';
return oss.str();
}
void fun2(int x, const std::string& name)
{
std::cout << x << ':' << name << std::endl;
}
void fun1()
{
for (unsigned int i = 0 ;i < 5 ; ++i )
{
fun2(i, array_str("testArray", i));
}
}
Test Output
0:testArray[0]
1:testArray[1]
2:testArray[2]
3:testArray[3]
4:testArray[4]
you can do like this..means in macros itself you have to display the desired string ..
#include<iostream>
#define STR1(x) #x
#define CREATE_INDEX(paramName,elementIndex) cout <<paramName<< "[" << elementIndex << "]"
#define CREATE_ARRAY_ELEM(paramName,elementIndex) CREATE_INDEX(paramName,elementIndex)
#define STRINGIZE_1(x) STR1(x)
using namespace std;
int main()
{
int testArray;
for (unsigned int i = 0 ;i < 5 ; ++i )
{
// I want to create a MACRO such that it create "testArray[0]","testArray[1]",..."testArray[4]" etc.
CREATE_ARRAY_ELEM ("testArray",i);
}
return 1;
}
Is it possible to stringify a character in a preprocessor macro without it including the (')s
example:
#define S(name, chr) const char * name = #name chr
usage:
S(hello, 'W'); //should expand to 'const char * hello = "helloW"
Thanks a bunch!,
Andrew
You don't need to, because in C adjacent string constants are merged.
ie.
const char *hello = "hello" "W";
is equivalent to
const char *hello = "helloW";
so your current macro is fine - just call it like so:
S(hello, "W");
Here are three ways. None use a single-quoted char, though:
#include <iostream>
#define S1(x, y) (#x #y)
#define S2(x, y) (#x y)
#define S3(x, y) (x y)
int main(void)
{
std::cout << S1(hello, W) << std::endl;
std::cout << S2(hello, "W") << std::endl;
std::cout << S3("hello", "W") << std::endl;
};
All output:
helloW