Compile time switch generation based on number of fields in structure

◇◆丶佛笑我妖孽 提交于 2020-01-17 11:17:11

问题


How in C++03 get in compile time number of members of chosen struct? I was experimenting with BOOST_FUSION_ADAPT_STRUCT but I did't get any working example.

I want to generate switch statement in compile time, where there will be one case per each member. So lets say we have struct with 3 members then I want to generate this switch:

switch(val)
{
   case 0:
       break;
   case 1:
       break;
   case 2:
       break;
}

In each statement I will call template function with some parameters. One of this parameters is a member of structure.

How I can do something like this?


回答1:


If you define the struct itself with BOOST_FUSION_DEFINE_STRUCT, boost will generate your struct in such a way that you can easily do this:

#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;
}

I modified the code above to also iterate over the members of the struct and apply a generic function. It seems like this functionally does the same thing as your hypothetical case statement would.

The reason you cannot pass the "2" this code generates to boost preprocessor macros is because the preprocessor runs first, before the code, you can't feed a number generate at compile time or at runtime into the preprocessor.

This program prints:

2
hey
5

See:

  1. BOOST_FUSION_DEFINE_STRUCT in boost::fusion documentation

  2. size in boost::fusion documentation

  3. Iterating over Boost fusion::vector




回答2:


After long searching, reading and finding this article. I managed to iterate over members from 0 to count - 1 (from that creating switch statement is easy).

#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")
}

Now BOOST_PP_REPEAT may create case statements.



来源:https://stackoverflow.com/questions/31712561/compile-time-switch-generation-based-on-number-of-fields-in-structure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!