Boost logo

Boost :

Subject: Re: [boost] [preprocessor] Variadics suggestion
From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2012-10-06 23:55:13


Well, here's what I have so far:

#define FLIP(...) __VA_ARGS__
#define FLOP(...) __VA_ARGS__

#define DO_FLIP(s, ...) \
     (CHAOS_PP_EXPR_S(s)(FLIP(__VA_ARGS__))) \
     /**/
#define DO_FLOP(s, ...) \
     CHAOS_PP_REM_CTOR(CHAOS_PP_EXPR_S(s)(FLOP(__VA_ARGS__))) \
     /**/

#define WAIT(m) \
     CHAOS_PP_IIF_SHADOW(CHAOS_PP_IS_NULLARY(m(())))( \
         WAIT_I, CHAOS_PP_EAT \
     )(m) \
     /**/
#define WAIT_ID() WAIT
#define WAIT_I(m) CHAOS_PP_DEFER(WAIT_ID)()(m)

#define FLAG(...) FLAG_A WAIT(FLIP)(__VA_ARGS__)
#define FLAG_A(...) FLAG_B WAIT(FLOP)() ) (,,,,,,,,,, __VA_ARGS__) (
#define FLAG_B() CHAOS_PP_DEFER(CHAOS_PP_EMPTY)(
#define FLAG_C() )

#define DROP(a, b, c, d, e, f, g, h, i, j, ...) __VA_ARGS__

#define ARG(n) FLAG(0XARG, n)

#define ARGS(...) \
     CHAOS_PP_QUICK_OVERLOAD(ARGS_, __VA_ARGS__)(__VA_ARGS__) \
     /**/
#define ARGS_1(n) FLAG(0XREST, n)
#define ARGS_2(n, m) \
     FLAG( \
         0XRANGE, n, \
         CHAOS_PP_INC(CHAOS_PP_SUB(m, n)) \
     ) \
     /**/

#define BIND(id) FLAG(0XBIND, id)

#define QS_HEAD(...) \
     CHAOS_PP_REM_CTOR(CHAOS_PP_SPLIT(0, QS_HEAD_I __VA_ARGS__)) \
     /**/
#define QS_HEAD_I(...) (__VA_ARGS__),

#define APPLY(args, ...) \
     APPLY_BYPASS(CHAOS_PP_LIMIT_EXPR, args, __VA_ARGS__) \
     /**/
#define APPLY_BYPASS(s, args, ...) \
     DO_FLOP( \
         s, \
         CHAOS_PP_EXPR_S(s)(APPLY_A(s, args, DO_FLIP(s, __VA_ARGS__))) \
     ) \
     /**/
#define APPLY_A(s, args, ...) \
     CHAOS_PP_IIF(CHAOS_PP_IS_VARIADIC(__VA_ARGS__))( \
         APPLY_C, APPLY_B \
     )(CHAOS_PP_OBSTRUCT(), CHAOS_PP_PREV(s), args, __VA_ARGS__) \
     /**/
#define APPLY_A_ID() APPLY_A
#define APPLY_B(_, s, args, ...) __VA_ARGS__
#define APPLY_C(_, s, args, ...) \
     APPLY_D(s, args, QS_HEAD(__VA_ARGS__)) \
     CHAOS_PP_EXPR_S _(s)(APPLY_A_ID _()( \
         s, args, CHAOS_PP_EAT __VA_ARGS__ \
     )) \
     /**/
#define APPLY_D(s, args, ...) \
     CHAOS_PP_CAT( \
         APPLY_, \
         CHAOS_PP_CAT( \
             0, \
             CHAOS_PP_VARIADIC_ELEM(0, DROP(__VA_ARGS__,,,,,,,,,,)) \
         ) \
     )(CHAOS_PP_OBSTRUCT(), s, args, __VA_ARGS__) \
     /**/
#define APPLY_0(_, s, args, ...) \
     (CHAOS_PP_EXPR_S _(s)(APPLY_A_ID _()( \
         s, args, __VA_ARGS__ \
     ))) \
     /**/
#define APPLY_00XARG(_, s, args, a, b, c, d, e, f, g, h, i, j, k, l) \
     CHAOS_PP_SEQ_ELEM(l, args) APPLY_E \
     /**/
#define APPLY_00XREST(_, s, args, a, b, c, d, e, f, g, h, i, j, k, l) \
     CHAOS_PP_SEQ_ENUMERATE( \
         CHAOS_PP_SEQ_DROP(l, args) \
     ) APPLY_E \
     /**/
#define APPLY_00XRANGE(_, s, args, a, b, c, d, e, f, g, h, i, j, k, l, m) \
     CHAOS_PP_SEQ_ENUMERATE( \
         CHAOS_PP_SEQ_TAKE(m, CHAOS_PP_SEQ_DROP(l, args)) \
     ) APPLY_E \
     /**/
#define APPLY_00XBIND(_, s, args, a, b, c, d, e, f, g, h, i, j, k, l) \
     APPLY_BIND_I WAIT(FLOP)(l) APPLY_E \
     /**/
#define APPLY_BIND_I(l) l CHAOS_PP_DEFER(CHAOS_PP_OBSTRUCT)()()
#define APPLY_E(...) __VA_ARGS__ FLAG_C WAIT(FLOP)()

Given the above, then

APPLY(
     (X)(Y),
     template<class T> class ARG(0) { };
     template<class T> class ARG(1) : public ARG(0)<T> {
         public:
             inline ARG(1)(const ARG(1)& o) : ARG(0)<T>(o) { }
     };
)

expands to

template<class T> class X { };

template<class T> class Y : public X<T> {
     public:
         inline Y(const Y& o) : X<T>(o) { }
};

Furthermore, ARGS(n) (i.e. plural) will result in all of the arguments
including and following the n-th argument, and ARGS(n, m) will result in
the arguments from the n-th argument to the m-th argument, inclusive. So,

APPLY(
     (A)(B)(?)(C)(D),
     { ARGS(0, 1), ARGS(3) }
)

results in { A, B, C, D }.

Lastly, the above defines a means of producing a binding on macro. For
example,

#define CAT_ BIND(CHAOS_PP_CAT_ID)

APPLY(
     (P)(Q),
     CAT_(ARGS(0))
)

results in CHAOS_PP_CAT_ID()(P, Q) which, when scanned as in

CHAOS_PP_EXPR(APPLY(
     (P)(Q),
     CAT_(ARGS(0))
))

results in PQ.

This doesn't work with all cases. For example:

APPLY(
     (int),
     void f(ARG(0));
)

results in an error. What probably needs to be done is something along
the lines of introducing commas (and flops that eat those commas) and
iterating over the elements of the non-flag tuples.

Regards,
Paul Mensonides


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk