Как перебрать две последовательности 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))
Другие вопросы по тегам