Как выполнить итерацию двух последовательностей препроцессора Boost одновременно?

Мне было интересно, можно ли сделать следующее с помощью последовательностей препроцессора Boost. (В большинстве вопросов SO, а также в примерах препроцессора Boost говорится только об одной последовательности)

#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 и переберите две последовательности.


person skgbanga    schedule 01.02.2017    source источник
comment
Почему не одну последовательность кортежей? Например. _1 _...   -  person Vittorio Romeo    schedule 01.02.2017
comment
На самом деле у меня есть 3-4 последовательности, и я прочитал этот вопрос: stackoverflow.com/questions/26475453/ Я предполагаю, что это потенциально можно сделать, но мне было интересно, есть ли способ для итерации по нескольким последовательностям, потому что эти последовательности макросов уже определены .   -  person skgbanga    schedule 01.02.2017
comment
Быстрый поиск показывает, что есть библиотека с zip-макросом: github.com /mcinglis/libpp/blob/master/zip.h   -  person chris    schedule 01.02.2017


Ответы (1)


Вы можете использовать BOOST_PP_SEQ_FOR_EACH_I и _ 2_, чтобы сделать это следующим образом:

#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))
person jotik    schedule 01.02.2017