I was wondering if the following can be done via Boost Preprocessor sequences. (Most of the SO questions as well as Boost Preprocessor examples talk about only 1 sequence)
#define seq1 (a)(b)(c)
#define seq2 (1)(2)(3)
// Now iterate over both of them at the same time
Here is my motivation. I have to define few functions for a lot of types e.g.
void add(int val) { obj.AddInt(val); }
void add(double val) { obj.AddDouble(val); }
I was thinking of defining two sequences like
#define types (int)(double)...
#define funcs (AddInt)(AddDouble)...
and then write a macro for the function add, and iterate over the two sequences.
You could use BOOST_PP_SEQ_FOR_EACH_I
and BOOST_PP_SEQ_ELEM
to do it as follows:
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#define types (int)(double)
#define funcs (AddInt)(AddDouble)
#define MACRO(_,funcs,i,type) \
void add(type val) { obj.BOOST_PP_SEQ_ELEM(i, funcs)(val); }
BOOST_PP_SEQ_FOR_EACH_I(MACRO, funcs, types)
The BOOST_PP_SEQ_FOR_EACH_I
macro iterates over the sequence types
, applying MACRO
to each element. The second argument to BOOST_PP_SEQ_FOR_EACH_I
is passed as the second argument to each invocation of MACRO
, and i
denotes the zero-based index of the current element being iterated over. Therefore, when MACRO
is being expanded, type
is the i
-th element of types
and BOOST_PP_SEQ_ELEM(i, funcs)
is the i
-th element of funcs
.
For a more general solution, you can do something like:
#define ITERATE_OVER_TWO_SEQ_(_,data,i,e2) \
BOOST_PP_SEQ_ELEM(0,data)(BOOST_PP_SEQ_ELEM(i, BOOST_PP_SEQ_ELEM(1,data)), e2)
#define ITERATE_OVER_TWO_SEQ(macro, s1, s2) \
BOOST_PP_SEQ_FOR_EACH_I(ITERATE_OVER_TWO_SEQ_, (macro)(s1), s2)
and use it as follows:
#define MACRO(type,func) void add(type val) { obj.func(val); }
ITERATE_OVER_TWO_SEQ(MACRO, types, funcs)
An even more generic way would be to use SEQ_ZIP
from this answer, BOOST_PP_SEQ_FOR_EACH
and BOOST_PP_SEQ_ELEM
. For example:
#include <boost/preprocessor/seq/for_each.hpp>
#define MACRO(_,d,seq) \
void add(BOOST_PP_SEQ_ELEM(0,seq) val) \
{ obj.BOOST_PP_SEQ_ELEM(1, seq)(val); }
BOOST_PP_SEQ_FOR_EACH(MACRO, _, SEQ_ZIP((types)(funcs))