Генерация переключателя времени компиляции на основе количества полей в структуре
Как в C++03 получить во время компиляции количество членов выбранной структуры? Я экспериментировал с BOOST_FUSION_ADAPT_STRUCT
но я не получил никакого рабочего примера.
Я хочу сгенерировать оператор switch во время компиляции, где будет один случай для каждого члена. Допустим, у нас есть структура с 3 членами, и я хочу сгенерировать этот ключ:
switch(val)
{
case 0:
break;
case 1:
break;
case 2:
break;
}
В каждом утверждении я буду вызывать шаблонную функцию с некоторыми параметрами. Один из этих параметров является членом структуры.
Как я могу сделать что-то подобное?
2 ответа
После долгих поисков, прочтения и нахождения этой статьи. Мне удалось перебрать членов от 0 до 1 (с этого легко создать оператор switch).
#include <iostream>
#include <string>
#include <vector>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/fusion/include/define_struct.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/seq/cat.hpp>
struct MyStruct
{
int x;
int y;
};
#define GO(r, data, elem) elem
#define SEQ1 ((int,x))((int,y))
BOOST_FUSION_ADAPT_STRUCT(
MyStruct,
BOOST_PP_SEQ_FOR_EACH(GO, ,SEQ1)
)
#define PRINT(unused, number, data) \
std::cout << number << std::endl;
int main()
{
BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(SEQ1), PRINT, "data")
}
Сейчас BOOST_PP_REPEAT
может создавать заявления случая.
Если вы определяете саму структуру с BOOST_FUSION_DEFINE_STRUCT
, boost сгенерирует вашу структуру таким образом, что вы можете легко сделать это:
#include <boost/fusion/include/define_struct.hpp>
#include <boost/fusion/include/size.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <iostream>
#include <string>
// demo::employee is a Fusion sequence
BOOST_FUSION_DEFINE_STRUCT(
(),
employee,
(std::string, name)
(int, age))
int main() {
employee e{"hey", 5};
int x = boost::fusion::size(e);
std::cerr << x << std::endl;
auto print = [] (auto v) { std::cerr << v << std::endl; };
boost::fusion::for_each(e, print);
return 0;
}
Я изменил код выше, чтобы также перебирать членов структуры и применять обобщенную функцию. Кажется, что это функционально делает то же самое, что и ваше гипотетическое утверждение.
Причина, по которой вы не можете передать "2", который этот код генерирует для повышения макросов препроцессора, заключается в том, что препроцессор запускается первым, перед тем как код не может передать число, сгенерированное во время компиляции или во время выполнения, в препроцессор.
Эта программа печатает:
2
hey
5
Увидеть: