0

Suppose I want to treat the arguments of a macro as pairs and then pass it to something else (expansively)

I imagine it looking something like this (pseudocode):

template<unsigned index,
         typename type>
struct my_pair
{
    static constexpr auto i = index;
    using t = type;
};
#define pair_off(...) my_pair<__VA_ARGS__[0], __VA_ARGS__[1]>, ...
nowi
  • 437
  • 4
  • 13
  • Why not stick to templates? IMHO, the strength of macros is still that they can turn identifiers into strings which is especially helpful if you try to implement any kind of reflection. Token pasting is another thing but it might be replaceable with nesting (e.g. with templates defining structs recursively). In C++, macros have the strong draw back that they are completely namespace agnostic (what can hurt you hard and unexpectedly). Please, provide a little bit more context of your actual problem to get a solution (with or without macros). – Scheff's Cat Apr 03 '20 at 05:28
  • My current situation is not possible with templates. https://stackoverflow.com/questions/61002624/alternating-template-parameters-pack – nowi Apr 03 '20 at 05:51
  • I understand. However, this other question in mind (which you should have mentioned/linked in this question)... I'm still not sure if it isn't an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) i.e. trying to solve something with (convoluted) macros which just should be designed differently. I stay to my request: Please, provide a little bit more context of your actual problem to get a solution (with or without macros). ;-) – Scheff's Cat Apr 03 '20 at 05:56
  • I'm making a tuple map – nowi Apr 03 '20 at 09:11

1 Answers1

0

With a variant of code from Is it possible to iterate over arguments in variadic macros? , you might do:

#define CONCATENATE(arg1, arg2)   CONCATENATE1(arg1, arg2)
#define CONCATENATE1(arg1, arg2)  CONCATENATE2(arg1, arg2)
#define CONCATENATE2(arg1, arg2)  arg1##arg2

#define FOR_EACH_BY_PAIR_2(what, x, y)\
  what(x, y)
#define FOR_EACH_BY_PAIR_4(what, x, y, ...)\
  what(x, y)\
  FOR_EACH_BY_PAIR_2(what,  __VA_ARGS__)
#define FOR_EACH_BY_PAIR_6(what, x, y, ...)\
  what(x, y)\
  FOR_EACH_BY_PAIR_4(what,  __VA_ARGS__)
#define FOR_EACH_BY_PAIR_8(what, x, y, ...)\
  what(x, y)\
  FOR_EACH_BY_PAIR_6(what,  __VA_ARGS__)

#define NARG(...) NARG_(__VA_ARGS__, RSEQ_N())
#define NARG_(...) ARG_N(__VA_ARGS__) 
#define ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N 
#define RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0

#define FOR_EACH_BY_PAIR_(N, what, ...) CONCATENATE(FOR_EACH_BY_PAIR_, N)(what, __VA_ARGS__)
#define FOR_EACH_BY_PAIR(what, ...) FOR_EACH_BY_PAIR_(NARG(__VA_ARGS__), what, __VA_ARGS__)

Limit is currently 8, up to you to increase that.

and then, you specific part:

#define MAKE_PAIR(x, y) COMMA my_pair<x, y>{}
#define COMMA ,
#define pair_off(p1, p2, ...) my_pair<p1, p2>{} FOR_EACH_BY_PAIR(MAKE_PAIR, __VA_ARGS__)

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • `FOR_EACH_BY_PAIR_X` are the different/unrolled for loop version. `NARG` is used to count va_args argument. From that value, we use correct MACRO. `what` is the customization point which would be called by each pair. – Jarod42 Apr 03 '20 at 09:55
  • Sorry, I didn't mean its usage. I meant how the macro actually functions - what makes it work? – nowi Apr 03 '20 at 09:56
  • Not sure what you mean, Can you be more specific? – Jarod42 Apr 03 '20 at 09:58