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.
Related
I have a preprocessor define that should determine the size of an array.
This constant should also be passed to a HLSL shader.
For this I need to pass it around as a string.
Is there a way to embed preprocessor defines as a string?
#include <iostream>
#ifndef SIZE
#define SIZE 16
#endif
int main() {
const int arr[SIZE] = {}; // array size is 16 :)
const char* str = "SIZE"; // literal is "SIZE" and not "16" :(
std::cout << str << std::endl; // should print "16"
std::cout << SIZE << std::endl; // prints 16, but is not a string
}
You can use a stringifying macro, eg:
#define STRINGIFY(x) STRINGIFY2(x)
#define STRINGIFY2(x) #x
const char* str = STRINGIFY(SIZE);
std::cout << str << std::endl;
Alternatively, use a runtime format via snprintf() or equivalent, eg:
char str[12];
snprintf(str, "%d", SIZE);
std::cout << str << std::endl;
However, you really should be using std::string in C++ instead of char*, eg:
#include <string>
std::string str = std::to_string(SIZE);
std::cout << str << std::endl;
Or:
#include <string>
#include <sstream>
std::ostringstream oss;
oss << SIZE;
std::cout << oss.str() << std::endl;
#include <iostream>
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define (__FILE__ ": " STR(__LINE__))
int main()
{
std::cout << FILE_LOCATION << std::endl;
return 0;
}
output:
main.cpp : __LINE__Var+1
Why line no doesn't shown?
I think you have to define your FILE_LOCATION macro, I cannot see the code where you define it in your snippet.
But wouldn't the code below do it?
#define FILE_LOCATION __FILE__ ": " STR(__LINE__)
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'm trying to code a macro called EMPTY_OR, which will return the first argument, but if it's empty, it will return the second one.
Here's what I have so far:
#include <iostream>
#define EMPTY_OR(x, y) ( (sizeof(#x) > sizeof("")) ? (x) : (y) )
#define TEST(x, y) EMPTY_OR(y, x)
using namespace std;
int main()
{
int four = TEST(4, );
int eight = TEST(4, 8);
cout << "four: " << four << endl;
cout << "eight: " << eight << endl;
return 0;
}
It's close, but it doesn't work because the first line of the main function expands to the following:
( (sizeof("") > sizeof("")) ? () : (4) )
The condition is never true, so () is never evaluated. I shouldn't care about it, but the compiler does, and it shows an error.
How can I solve it with the most straightforward and standard-compliant (or at least MSVC-compliant) way?
If I'm understanding what you're trying to do correctly, I'd remove the sizeof and just check if the first character in the string is \0;
#define EMPTY_OR(x, y) ( #x[0] ? (x+0) : (y) )
Here's a solution adapted from this article and without Boost that works on anything that I can think of that you can pass:
#define CAT(a, b) CAT_(a, b)
#define CAT_(a, b) a##b
#define IF(cond, t, f) CAT(IF_, cond)(t, f)
#define IF_1(t, f) t
#define IF_0(t, f) f
#define COMMA(x) ,
#define ARG3(a, b, c, ...) c
#define HAS_COMMA(x) ARG3(x, 1, 0,)
#define EMPTY(x) EMPTY_(HAS_COMMA(COMMA x ()))
#define EMPTY_(x) HAS_COMMA(CAT(EMPTY_, x))
#define EMPTY_1 ,
#define EMPTY_OR(x, y) IF(EMPTY(x), y, x)
#define TEST(x, y) EMPTY_OR(y, x)
#include <iostream>
using namespace std;
int main()
{
int t = TEST(1==, ) 1;
int f = TEST(1==, 0==) 1;
cout << "t: " << t << endl;
cout << "f: " << f << endl;
return 0;
}
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;
}