Portably detect __VA_OPT__ support?

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.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)