Reputation: 1283
Say I have a C macro-defined product version like this:
#define FOO_VERSION 1,0,0,1
And I want to print it at run-time:
#define STRING_VALUE(x) #x
int main()
{
std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}
This will output a string "FOO_VERSION", not "1,0,0,1". The macro argument 'FOO_VERSION' is not replaced. So I try it again like this:
#define STRING_VALUE(x) STRING_VALUE__(x)
#define STRING_VALUE__(x) #x
int main()
{
std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}
It works, in Visual C++ 2013.
This is a cross-platform application although there are only five lines of code. When I use clang to compile the code, a compile- time error appears: "too many arguments provided to function-like macro invocation". I guess the reason is the comma defined in 'FOO_VERSION'. So the third version:
#define STRING_VALUE(x) STRING_VALUE__(x)
#define STRING_VALUE__(a, b, c, d) #a "," #b "," #c "," #d
int main()
{
std::cout << STRING_VALUE(FOO_VERSION) << std::endl;
}
This code works in clang, but Visual C++ will output a warning: "not enough actual parameters for macro 'STRING_VALUE__'" at compile-time, of course the run-time output is not right.
My question: is this pre-processor behavior defined ? Can I have a universal version of STRING_VALUE macro ?
Upvotes: 6
Views: 1177
Reputation: 29126
You can treat the argument as a single variadic macro:
#define FOO_VERSION 1,0,0,1
#define STRING_VALUE(...) STRING_VALUE__(__VA_ARGS__)
#define STRING_VALUE__(...) #__VA_ARGS__
This seems to work with gcc and Visual C++.
Upvotes: 11