In C++20, the preprocessor supports __VA_OPT__
as a way to optionally expand tokens in a variadic macro if the number of arguments is greater than zero. (This obviates the need for the ##__VA_ARGS__
GCC extension, which is a non-portable and ugly hack.)
Clang SVN has implemented this feature, but they haven't added a feature test macro for it. Can any clever preprocessor hacker figure out a way to detect the presence or absence of __VA_OPT__
support without causing a hard error or a portability warning?
Inspired by chris's answer.1
#define PP_THIRD_ARG(a,b,c,...) c
#define VA_OPT_SUPPORTED_I(...) PP_THIRD_ARG(__VA_OPT__(,),true,false,)
#define VA_OPT_SUPPORTED VA_OPT_SUPPORTED_I(?)
If __VA_OPT__
is supported, VA_OPT_SUPPORTED_I(?)
expands to PP_THIRD_ARG(,,true,false,)
, so the third argument is true
; otherwise, VA_OPT_SUPPORTED_I(?)
expands to PP_THIRD_ARG(__VA_OPT__(,),true,false,)
, the third argument is false
.
Edit: As Edward Diener's answer notes, GCC >= 8 issues a warning or error whenever it sees __VA_OPT__
, if -pedantic
mode is on and __VA_OPT__
is not enabled (e.g. in -std=c++17
). This is GCC bug 98859. One might have to special-case GCC to avoid this diagnostic.
#if __cplusplus <= 201703 && defined __GNUC__ \
&& !defined __clang__ && !defined __EDG__ // These compilers pretend to be GCC
# define VA_OPT_SUPPORTED false
#endif
1. As chris mentions, if __VA_OPT__(,)
expands to ,
, there will be 2 empty arguments, otherwise there will be 1 argument. So it's possible to test PP_NARG(__VA_OPT__(,)) == 2
, where PP_NARG
is a macro to count the number of arguments. To adapt to this test, the definition of PP_NARG
can be simplified and inlined.