Генерация переключателя времени компиляции на основе количества полей в структуре

Как в 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

Увидеть:

  1. BOOST_FUSION_DEFINE_STRUCT в Boost:: документация Fusion

  2. размер в надстройке:: документация Fusion

  3. Итерация по Boost Fusion:: Vector

Другие вопросы по тегам