1

I would like to expand a variadic macro to another macro that takes a single argument, which is formed by joining the variadic arguments with a delimiter/separator (e.g. "_"). Something like this:

#define FOO(...)

FOO(a, b, c, d);

which expands into

#define BAR(X)

BAR(a_b_c_d);

I know there is __VA_ARGS__ for working with the variadic parameters, and ## for concatenation. How do I use them together to achieve what I want (preferably using C++17 and older language features, without libraries such as Boost)?

  • you need to concatenate yje values of the variables, not their names. also consider using a variadic template – Neil Butterworth Nov 20 '22 at 03:21
  • 1
    You might want to check [Boost.Preprocessor](https://www.boost.org/doc/libs/1_80_0/libs/preprocessor/doc/index.html) – Ranoiaetep Nov 20 '22 at 03:22
  • @NeilButterworth Thanks for catching this mistake! I amended my question to only about expansion to another macro. – Wowbagger and his liquid lunch Nov 20 '22 at 03:29
  • @Ranoiaetep Thanks for this suggestion. However, I'm working on a code base that's not likely to add Boost as a dependency. I amended my question to clarify this. Although, I think this is still a very good suggestion. Do you know which Boost header has the relevant macro definition, so that I can take a look at the source and learn how they did it? – Wowbagger and his liquid lunch Nov 20 '22 at 03:33
  • 2
    Libraries like Boost.PP offer this with a lot of ugliness hidden behind the scenes. Given that PP libraries tend to be pretty dependency-free (you don't need all of Boost just for Boost.PP for example, literally zero other parts of Boost [according to this](https://pdimov.github.io/boostdep-report/boost-1.80.0/preprocessor.html)), I'd highly recommend not subjecting yourself to recreating the ugliness if you can avoid it. Depending what your ultimate goal is, there might also be a macro-free alternative. – chris Nov 20 '22 at 03:35
  • Why not use a variadic template instead? – Jesper Juhl Nov 20 '22 at 13:53

1 Answers1

1

First, there are no language feature that directly tackles the question you are trying to solve. (there might be complier specific ones, but I don't know).


However, if you know the upper limit of the amount of argument that macro can take(preferably not too many), you can use this answer as a guide to iterate through the __VA_ARGS__: Is it possible to iterate over arguments in variadic macros?


On the other hand, Boost.Preprocessor is a header only library. While it is a pretty heavy macro-only library that could bring a lot of ugliness behind the scene, it does offer simple ways to handle macros that take up to thousands of parameter.

Here's a quick one that should work for you:

#define CAT_OP(index, state, elem) BOOST_PP_CAT(state, BOOST_PP_CAT(_, elem))
#define CAT_SEQ(seq) BOOST_PP_SEQ_FOLD_LEFT(CAT_OP, BOOST_PP_SEQ_HEAD(seq), BOOST_PP_SEQ_TAIL(seq))
#define CAT_VA_ARGS(...) CAT_SEQ(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))

Demo.

It treats the variadic as a Sequence, then performs a left fold over the sequence with concat operation.

Ranoiaetep
  • 5,872
  • 1
  • 14
  • 39