I have some code that needs Unicode strings for the most part, but I want to make it conditional (ie, TEXT("string") expanding to L"string" or "string", depending on settings). For these, I use the macro:
#ifdef _UNICODE
# define VSTR(str) L##str
#else
# define VSTR(str) str
#endif
The main complication with this is printf format strings, which use %s and %S for same-encoding and other-encoding strings, respectively. Some strings come from similarly conditional APIs (TCHAR and similar), while some come from set APIs (mostly C-string only). When using _tprintf and family, the function used can vary making %s and %S conditional as well, and they may need to be flipped around. To handle this, I defined macros to the appropriate format elements:
#ifdef _UNICODE
# define VPFCSTR(str) "%S"
# define VPFWSTR(str) "%s"
# define VPFTSTR(str) VPFWSTR(str)
#else
# define VPFCSTR(str) "%s"
# define VPFWSTR(str) "%S"
# define VPFTSTR(str) VPFCSTR(str)
#else
Now, this all works fine, but forces the syntax:
VSTR("Beginning of a format string, with a string '") VPFTSTR VSTR("' included.")
I would like to be able to use a syntax like:
VSTR("Beginning of a format string, with a string '", VPFTSTR, "' included.")
For Unicode, this needs to expand to:
L"Beginning of a format string, with a string '" L"%s" L"' included."
The only complication is the variable number of arguments, all of which need to be transformed in the same manner (one by one, if necessary).
My first idea was to use __VA_ARGS__ to handle this, using empty arguments, like:
VASTR(str, ...) VSTR(str) VASTR(__VA_ARGS__)
Unfortunately, as macros can't be used in their own definition, this fails. I then attempted a proxy:
VASTR2(...) VASTR(__VA_ARGS__)
VASTR(str, ...) VSTR(str) VASTR2(__VA_ARGS__)
The proxy method doesn't appear to work either.
Is there a way to handle running the same macro on each argument of a(nother) macro, which takes a variable number of arguments? Or, if not, is there an equivalent? If compiler-specific, MSVC10 is preferred, but anything is of interest.
Recursive macro expansion is not possible in C/C++.
Not sure, but C++0x allows you to omit encoding prefix for string literal concatenation. Thus you can try design your macro to prepend L only to the first string literal and use it as follows:
VSTR("Beginning of a format string, with a string '" VPFTSTR "' included.")
Please, correct me, if I'm wrong.
UPD.
A similar Unicode-related question: What happens with adjacent string literal concatenation when there is a modifier(L, u8, etc.)
Using the Boost.Preprocessor library, and these additional macros, you can apply your VSTR macro to each argument:
//Your VSTR macro for one argument
#define VSTR_EACH(str) ...
/**
* PP_NARGS returns the number of args in __VA_ARGS__
*/
#define PP_NARGS(...) \
PP_DETAIL_NARG((__VA_ARGS__,PP_DETAIL_RSEQ_N()))
#define PP_DETAIL_NARG(args) \
PP_DETAIL_ARG_N args
#define PP_DETAIL_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define PP_DETAIL_RSEQ_N() \
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
//Convert agruments list to a BOOST_PP_SEQ so we can iterate over it
//This is two macros in order to avoid the bug in MSVC compilers
#define DETAIL_PP_ARGS_TO_SEQ(size, tuple) BOOST_PP_TUPLE_TO_SEQ(size, tuple)
#define PP_ARGS_TO_SEQ(...) DETAIL_PP_ARGS_TO_SEQ(PP_NARGS(__VA_ARGS__), (__VA_ARGS__))
//The macro used inside of BOOST_PP_SEQ_FOR_EACH
#define VSTR_SEQ_EACH(t, data, x) VSTR_EACH(x)
#define VSTR(...) BOOST_PP_SEQ_FOR_EACH(VSTR_SEQ_EACH, ~, PP_ARGS_TO_SEQ(__VA_ARGS__))
Related
I'm working with WPP (Windows Tracing) and the basic macro looks like this:
trace(SEVERITY, SOURCE, "%s started", app_name);
I would like to do is something like this but I get a variety of compiler/trace errors:
#define trace_with_console(__level, __flags, __format, ...) \
do \
{ \
printf(__format, __VA_ARGS__); \
trace(__level, __flags, __format, ...); \
} while (false);
Is there a correct way to call the trace macro from the trace_with_console macro?
EDIT: Thank you everyone for replying. The problem isn't a macro issue, it is the WPP for Windows trace processor failing.
This tool parses the trace macro call and extracts the text to keep it secret, and replaces it with a GUID. You need debugging information to read the traces.
The processor gets confused by the trace macro being called within this context. At this stage it doesn't seem possible to do what I'm trying to do. #jxh answer works well, just not with WPP.
Thank you all again!
Without knowing anything about the trace() macro or function other than how you are trying to invoke it, I would rewrite your proposed macro as:
#define trace_with_console(__level, __flags, __format, ...) \
do \
{ \
printf(__format, __VA_ARGS__); \
trace(__level, __flags, __format, __VA_ARGS__); \
} while (false)
Replace the ... in the call to trace with __VA_ARGS__ instead. The contents of the variable arguments represented by ... in your arg list for trace_with_console will be used in the expansion of __VA_ARGS__.
Remove the ; at the last line of your macro. This allows your macro to be treated as a statement that requires a ; at the end.
One disadvantage with the macro as it is written is that there are arguments that will be evaluated twice. Once evaluation will happen in the call to printf, and another evaluation in the call to trace.
Since __format and __VA_ARGS__ are being passed into printf, we assume trace can accept the same format specifications and corresponding arguments. Then, if there is a reasonable max size for your trace message, you may avoid multiple argument evaluation by using snprintf.
#define trace_with_console(__level, __flags, __format, ...) \
do \
{ \
char __buf_for_trace[BUF_FOR_TRACE_MAX_SIZE]; \
snprintf(__buf_for_trace, sizeof(__buf_for_trace), \
__format, __VA_ARGS__); \
printf("%s", __buf_for_trace); \
trace(__level, __flags, "%s", __buf_for_trace); \
} while (false)
In C++, you can remove the macro and use a variadic template function instead.
template <typename LevelType, typename FlagsType, typename... Types>
void trace_with_console (
LevelType level, FlagsType flags,
const char *format, Type... args) {
printf(format, args...);
trace(level, flags, format, args...);
}
What's the way to implement a standard-compliant assert macro with an optional formatted message?
What I have works in clang, but (correctly) triggers the -Wgnu-zero-variadic-macro-arguments warning if it is turned on (e.g. via -Wpedantic) when the macro is used without the optional message. Wandbox
#define MyAssert(expression, ...) \
do { \
if(!(expression)) \
{ \
printf("Assertion error: " #expression " | " __VA_ARGS__); \
abort(); \
} \
} while(0)
One needs to really use the preprocessor to the max in order to differentiate no additional arguments from the case where they are present. But with Boost.PP one can do this:
#include <boost/preprocessor/variadic/size.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/logical/bool.hpp>
#include <boost/preprocessor/cat.hpp>
#define MyAssert(...) BOOST_PP_CAT(MY_ASSERT,BOOST_PP_BOOL(BOOST_PP_SUB(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), 1)))(__VA_ARGS__)
#define MY_ASSERT0(expr) MY_ASSERT1(expr,)
#define MY_ASSERT1(expression, ...) \
do { \
if(!(expression)) \
{ \
std::printf("Assertion error: " #expression " | " __VA_ARGS__); \
std::abort(); \
} \
} while(0)
MyAssert must accept at least one argument (standard). Then we count the arguments, subtract one, and turn to a boolean (0 or 1). This 0 or 1 is concatenated to the token MY_ASSERT to form a macro name, to which we proceed to forward the arguments.
MY_ASSERT1 (with args), is your original macro. MY_ASSERT0 substitutes itself with MY_ASSERT1(expr,), the trailing comma means we pass another argument (thus fulfilling the requirement for the one extra argument), but it is an empty token sequence, so it does nothing.
You can see it live.
Since we already went down this rabbit hole, if one doesn't want to pull in Boost.PP the above can be accomplished with the usual argument counting trick, slightly adapted. First, we must decide on a maximum limit for the arguments we allow. I chose 20, you can choose more. We'll need the typical CONCAT macro, and this macro here:
#define HAS_ARGS(...) HAS_ARGS_(__VA_ARGS__,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,)
#define HAS_ARGS_(a1,a2,a3,a4,a5,b1,b2,b3,b4,b5,c1,c2,c3,c4,c5,d1,d2,d3,d4,d5,e, N, ...) N
It's argument counting, but with a twist. When __VA_ARGS__ is a single argument (no extra ones), the N resolved as 0. Otherwise, it is resolved as 1. There can be up to 20 extra arguments after the expression, any number of which will resolve to the same 1. Now we just plug it into the same place we used boost before:
#define MyAssert(...) CONCAT(MY_ASSERT, HAS_ARGS(__VA_ARGS__))(__VA_ARGS__)
You can tinker with it here
I have a solution which I'm not particularly proud of..
We can obtain the first argument in plain form and as a string using:
#define VA_ARGS_HEAD(N, ...) N
#define VA_ARGS_HEAD_STR(N, ...) #N
Note that in usage, in order to not get warnings, you should do VA_ARGS_HEAD(__VA_ARGS__, ) (with the extra ,) so that VA_ARGS_HEAD is never used with a single parameter (trick taken from StoryTeller's answer).
We define the following helper function:
#include <stdarg.h>
#include <stdio.h>
inline int assertionMessage(bool, const char *fmt, ...)
{
int r;
va_list ap;
va_start(ap, fmt);
r = vprintf(fmt, ap);
va_end(ap);
return r;
}
When the assertion has a format string, the function would work with __VA_ARGS__ as is, however when the bool is the only argument, we're missing a format string. That's why we'll add another empty string after __VA_ARGS__ when invoking it:
#define MyAssert(...) \
do { \
if(!(VA_ARGS_HEAD(__VA_ARGS__, ))) \
{ \
printf("Assertion error: %s | ", VA_ARGS_HEAD_STR(__VA_ARGS__, )); \
assertionMessage(__VA_ARGS__, ""); \
abort(); \
} \
} while(0)
Note that assertionMessage doesn't have printf in its name. This is deliberate and intended to avoid the compiler giving format-string related warnings for its invocations with the extra "" argument. The down-side for this is that we don't get the format-string related warnings when they are helpful.
The basic solution is to use << on cerr:
#define MyAssert(expression, msg) \
do { \
if(!(expression)) \
{ \
std::cerr << msg; \
abort(); \
} \
} while(0)
This solution uses C++ streams, so you can format the output as you see fit. Actually this is a simplification of a C++17 solution that I'm using to avoid temporaries (people tend to use + instead of << with this solution, triggering some efficiency warnings).
Use it then like this:
MyAssert(true, "message " << variable << " units");
I think the optionality is bogus here, as you are outputting "Assertion error:" meaning that you expect a message.
I read quite a few questions on SO about variadic macros now, but it doesn't seem like anyone answered the most simple question:
#define IDENTITY(x) x
#define IDENTITY_FOR_ALL(...) ???
Is there a way to make IDENTITY_FOR_ALL expand to IDENTITY(X) for all arguments? Is it also possible for arbitrary numbers of arguments?
There is no such thing as a pack expansion for variadic macros as there is for variadic templates.
You could use Boost.Preprocessor (or its methods) though.
If you don't want any commas between the elements, use
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
#define ID_OP(_, func, elem) func(elem)
#define APPLY_TO_ALL(func, ...) \
BOOST_PP_SEQ_FOR_EACH( \
ID_OP, func, \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) \
)
// example call:
#define SomeTransformation(x) #x // stringize the argument
APPLY_TO_ALL(SomeTransformation, 1, 2, 3) // expands to "1" "2" "3"
Demo.
With commas:
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/seq/transform.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
#define ID_OP(_, func, elem) func(elem)
#define APPLY_TO_ALL(func, ...) \
BOOST_PP_SEQ_ENUM( \
BOOST_PP_SEQ_TRANSFORM( \
ID_OP, func, \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) \
))
// example call:
APPLY_TO_ALL(SomeTransformation, 1, 2, 3) // expands to "1", "2", "3"
Demo.
Check the preprocessor output with g++ -std=c++11 -E -P file.
Assuming you need a PP solution, you can use BOOST_PP_REPEAT:
//invoke IDENTITY_FOR_ALL_MACRO with each index and the given tuple
#define IDENTITY_FOR_ALL(...) \
BOOST_PP_REPEAT( \
BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
IDENTITY_FOR_ALL_MACRO, \
BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__) \
)
//use the index to access the right element of the passed tuple
#define IDENTITY_FOR_ALL_MACRO(z, n, data) \
IDENTITY(BOOST_PP_TUPLE_ELEM(n, data))
IDENTITY_FOR_ALL(abc, 123, "woopee")
//translated to abc 123 "woopee"
It would be decently straightforward to turn this into a more general macro that takes a macro to invoke and the list of single arguments to pass one by one if you need to do this with several different macros and not just IDENTITY.
I'm not 100% sure what you mean by an arbitrary number of arguments, but if you want to invoke IDENTITY with two arguments at a time instead of one, you can change the bottom macro to use BOOST_PP_MUL and BOOST_PP_INC to access the "2n"th and "2n+1"th elements of the tuple, and then invoke the macro only half as many times in the REPEAT call.
I'm using the macros from this post looping through my arguments. Everything works great! However, is there a way to combine these two CCB_CREATE and CCB_CREATE_MORE?
I need to extract the first argument object_type to write additional code. The additional object_types will be using the FOR_EACH loop to insert into the map.
The compiler complaints when I only have one argument when using CCB_CREATE_MORE(Type1). To fix that I made another macro to handle that CCB_CREATE(Type1). Hoping to find a clever solution to combine these two into one elegant macro. Any ideas?
#define INSERT_LOADER_MAP(object_type) loader_map.insert(make_pair(#object_type, object_type##Loader::loader()))
#define CCB_CREATE_MORE(object_type,...) \
static CCNode * create##object_type##Node() { \
std::map<std::string, CCNodeLoader*> loader_map; \
std::string classname = #object_type; \
FOR_EACH(INSERT_LOADER_MAP,object_type,__VA_ARGS__); \
return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}
#define CCB_CREATE(object_type) \
static CCNode * create##object_type##Node() { \
std::map<std::string, CCNodeLoader*> loader_map; \
std::string classname = #object_type; \
INSERT_LOADER_MAP(object_type); \
return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}
The compiler is likely complaining about the trailing comma when the variadic arguments list is empty. GCC and Visual Studio compilers support the non-standard extension ##__VA_ARGS__ to suppress the trailing comma:
#define FOO(fmt, ...) printf(fmt, ##__VA_ARGS__)
The Visual Studio compilers will also suppress the trailing comma even without the ## extension.
See GCC documentation here, and Visual Studio documentation here.
If you need a standards-compliant solution, there is one detailed in an answer to this question.
So if you are using either gcc or Visual Studio, you should be able to use your original macro with this simple change:
#define CCB_CREATE(object_type,...) \
static CCNode * create##object_type##Node() { \
std::map<std::string, CCNodeLoader*> loader_map; \
std::string classname = #object_type; \
FOR_EACH(INSERT_LOADER_MAP,object_type,##__VA_ARGS__); \
return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}
Edit:
You would need to use the ##__VA_ARGS__ extension in the FOR_EACH() macro as well, or the more elegant modification suggested by ugoren.
#define FOR_EACH(what, x, ...) FOR_EACH_(FOR_EACH_NARG(x, ##__VA_ARGS__), what, x, __VA_ARGS__)
In addition to Chris Olsen's suggestion, a slight change to the FOR_EACH macro is needed:
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
As a result, FOR_EACH(X, a) will become X(a) (instead of X(a); X();). This eliminates an empty INSERT_LOADER_MAP invocation.
One may generally use __LINE__ and __FILE__ in C++ programs, with many toolchains, including GCC.
__LINE__ under GCC evaluates to an expression of type int;
__FILE__ evaluates to a char const[N] where N is the appropriate value.
Does any major toolchain provide an equivalent to __FILE__ with type wchar const[N]?
If so, what is it?
You can make your own WFILE:
#define WIDE2(x) L##x
#define WIDE1(x) WIDE2(x)
#define WFILE WIDE1(__FILE__)
Tested with non-ASCII characters and filename 马克.cpp:
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#define WIDE2(x) L##x
#define WIDE1(x) WIDE2(x)
#define WFILE WIDE1(__FILE__)
int main() {
_setmode(_fileno(stdout), _O_U16TEXT); // required for Unicode output to console
wprintf(L"%s\n", WFILE);
}
Demo (running from cmd.exe and Chinese language support installed):
C:\>cl /W4 /nologo 马克.cpp
马克.cpp
C:\>马克.exe
马克.cpp
Use:
WIDE(MEXPAND(__FILE__))
and
WIDE(STRINGIFY(__LINE__))
or replace __LINE__ with anything that needs to be stringified, and replace __FILE__ with any macro string literal you want to widen.
Using the following definitions:
#define STRINGIFY2(m) #m
#define MEXPAND(m) m
#define STRINGIFY(m) STRINGIFY2(m)
#define WIDE(m) L ## m
Example usage:
#define AssertBreakMethod DebugBreak
#define AssertBreakForce(expr) \
do \
{ \
if (!(expr)) \
{ \
OutputDebugStringW(WIDE(MEXPAND(__FILE__)) \
WIDE("(") WIDE(STRINGIFY(__LINE__)) \
WIDE("): Assertion failed: ") \
WIDE(#expr) WIDE("\n")); \
AssertBreakMethod(); \
} \
} \
while (0)
Note that the whole parameter to OutputDebugString is assembled statically at compile time into a single string literal.
The trick with stringification of a macro is passing it through another macro. When __FILE__ is passed to MEXPAND it is expanded at that time. MEXPAND returns its argument which is now a string. It is then legal to put the leading L there to make it wide.
STRINGIFY does the same trick, it passes its argument through STRINGIFY2 which expands the argument to the line number (which looks like an integer at that point) then STRINGIFY2 puts the # symbol before it, stringifying the integer.
In Visual Studio just surround it with _T(), for example:
TRACE( _T("function = %s"), _T(__FUNCTION__);
I would have put this answer as a comment to an earlier reply but was not allowed due to not having the minimum 50 reputation to comment...
In Visual Studio, _T(__FILE__) will NOT expand to L__FILE__ unless you modify its standard definition of _T in the tchar.h header file. _T(__FILE__) and _T(__FUNCTION__) worked 5 years ago and still work today if you are looking for wide versions of the current file and function.
_T(x) is defined as __T(x), which is defined as L##x when _UNICODE is defined and x otherwise. So _T(__FILE__) expands to something like __T("my_file.c"), which then expands to L"my_file.c" or "my_file.c" depending on _UNICODE. It is useful to test things before claiming that they do not work.
For example use const auto name = L"" __FUNCTION__;