#include <boost/preprocessor/seq/to_tuple.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/fold_left.hpp>
#include <boost/preprocessor/seq/replace.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/cat.hpp>

#define GEN_TUPLE2SEQ_PROCESS2(x, y) \
  ((x, y)) \
  GEN_TUPLE2SEQ_PROCESS

#define GEN_TUPLE2SEQ_PROCESS(x, y) \
  ((x, y)) \
  GEN_TUPLE2SEQ_PROCESS2

#define GEN_TUPLE2SEQ_PROCESS_ELIM
#define GEN_TUPLE2SEQ_PROCESS2_ELIM

#define GEN_TUPLE2SEQ(x) \
  BOOST_PP_CAT(GEN_TUPLE2SEQ_PROCESS x, _ELIM)

#define PARAM_CHANGES(prefix, x) \
  ((0, BOOST_PP_SEQ_ELEM(0, BOOST_PP_CAT(prefix, _INITIAL)))) \
  BOOST_PP_SEQ_FOR_EACH( \
    PARAM_EXPAND, \
    prefix, \
    GEN_TUPLE2SEQ(x))

#define PARAM_EXPAND(r, prefix, e) \
  PARAM_EXPAND2( \
    BOOST_PP_CAT(BOOST_PP_CAT(prefix, __), BOOST_PP_TUPLE_ELEM(2, 0, e)), \
    BOOST_PP_TUPLE_ELEM(2, 1, e))

#define PARAM_EXPAND2(x, y) \
  ((x(y)))

#define PARAM_COMBINE(s, state, x) \
  BOOST_PP_SEQ_REPLACE( \
    state, \
    BOOST_PP_TUPLE_ELEM(2, 0, x), \
    BOOST_PP_TUPLE_ELEM(2, 1, x))

#define PARAM_INVOKE2(prefix, x) \
  BOOST_PP_SEQ_TO_TUPLE( \
    BOOST_PP_SEQ_FOLD_LEFT( \
      PARAM_COMBINE, \
      BOOST_PP_CAT(prefix, _INITIAL), \
      PARAM_CHANGES(prefix, x)))

#define PARAM_INVOKEx(macro, x) \
  macro x

#define PARAM_INVOKE(prefix, x) \
  PARAM_INVOKEx(prefix, PARAM_INVOKE2(prefix, x))

/*
Use like:

#define xPARAM__name(x)           0, x
#define xPARAM__n(x)              xPARAM__name(x)
#define xPARAM__fixture(x)        1, (1, x)
#define xPARAM__f(x)              xPARAM__fixture(x)
#define xPARAM__group_fixture(x)  2, x
#define xPARAM__gf(x)             xPARAM__group_fixture(x)
#define xPARAM__generator(x)      3, (1, x)
#define xPARAM__gen(x)            xPARAM__generator(x)

#define xPARAM_INITIAL \
  ("") ((0, ~)) (0) ((0, ()))

#define xPARAM(a, b, c, d) \
  A = a; \
  B = b; \
  C = c; \
  D = d;

#define MACRO(x) PARAM_INVOKE(xPARAM, x)

MACRO((n, 2)(f, x))

which will result in:

A = 2; B = (1, x); C = 0; D = (0, ());
*/

