Как перебрать две последовательности Boost Preprocessor одновременно?
Мне было интересно, можно ли сделать следующее с помощью последовательностей Boost Preprocessor. (Большинство вопросов SO, а также примеры Boost Preprocessor говорят только об одной последовательности)
#define seq1 (a)(b)(c)
#define seq2 (1)(2)(3)
// Now iterate over both of them at the same time
Вот моя мотивация. Я должен определить несколько функций для многих типов, например
void add(int val) { obj.AddInt(val); }
void add(double val) { obj.AddDouble(val); }
Я думал об определении двух последовательностей, таких как
#define types (int)(double)...
#define funcs (AddInt)(AddDouble)...
а затем напишите макрос для функции add и выполните итерации по двум последовательностям.
1 ответ
Вы могли бы использовать BOOST_PP_SEQ_FOR_EACH_I
а также BOOST_PP_SEQ_ELEM
сделать это следующим образом:
#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)
BOOST_PP_SEQ_FOR_EACH_I
макрос перебирает последовательность types
, применяя MACRO
к каждому элементу. Второй аргумент BOOST_PP_SEQ_FOR_EACH_I
передается в качестве второго аргумента для каждого вызова MACRO
, а также i
обозначает нулевой индекс текущего элемента, который повторяется. Поэтому, когда MACRO
расширяется, type
это i
элемент types
а также BOOST_PP_SEQ_ELEM(i, funcs)
это i
элемент funcs
,
Для более общего решения вы можете сделать что-то вроде:
#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)
и используйте его следующим образом:
#define MACRO(type,func) void add(type val) { obj.func(val); }
ITERATE_OVER_TWO_SEQ(MACRO, types, funcs)
Еще более общий способ будет использовать SEQ_ZIP
из этого ответа, BOOST_PP_SEQ_FOR_EACH
а также BOOST_PP_SEQ_ELEM
, Например:
#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))