2

I wrote this variadic macro template<>-maker.

#define TNAME0()
#define TNAME1(_1)        typename _1
#define TNAME2(_1,_2)     typename _1, typename _2
#define TNAME3(_1,_2,_3)  typename _1, typename _2, typename _3
#define TYPENAMES(_0,_1,_2,_3,n,...) TNAME##n
#define T(types...)   template< TYPENAMES(,##types,3,2,1,0)(types) >

It works great with GNU C++ (e.g. T(),T(U),T(U,V),...), but fails with 0 args using ISO C++ standard (calls TYPES1 instead of TYPES0).

Is there a fix that works with both GNU and ISO c++?

3
  • Demo on godbolt Commented Jan 30, 2022 at 20:39
  • @Brian Yes, that's the problem.
    – codechimp
    Commented Jan 30, 2022 at 20:44
  • 1
    Unfortunately before C++20's __VA_OPT__, there is no standard-compliant way to have the preprocessor do different things with T() and T(Arg).
    – aschepler
    Commented Jan 30, 2022 at 21:49

1 Answer 1

3

This syntax for variadic macros isn't standard C++ at all:

#define T(types...)

Instead you can use an unnamed ..., which is referred to by __VA_ARGS__ in the expansion. Since C++20 you can also use __VA_OPT__(,) to include the initial , only if ... isn't empty:

#define T(...)   template< TYPENAMES(__VA_OPT__(,) __VA_ARGS__,3,2,1,0)(__VA_ARGS__) >

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.