【问题标题】:Compile time switch generation based on number of fields in structure根据结构中的字段数编译时间开关生成
【发布时间】:2015-07-29 22:57:39
【问题描述】:

在 C++03 中如何在编译时获取所选结构的成员数?我正在尝试使用 BOOST_FUSION_ADAPT_STRUCT,但没有得到任何可行的示例。

我想在编译时生成 switch 语句,每个成员都有一个 case。所以假设我们有 3 个成员的结构然后我想生成这个开关:

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

在每个语句中,我将调用带有一些参数的模板函数。其中一个参数是结构的成员。

我怎么能做这样的事情?

【问题讨论】:

  • 使用容器,例如std::vectorstd::map 之类的?或者进一步解释为什么那些不能达到你希望达到的效果......
  • 容器与计算 struct 的成员有很大不同,如果 op 已经研究过像 fusion 这样的高级库,我认为我们应该让他怀疑他是否真的需要它。
  • @NirFriedman:真的吗?这将是我第一次看到“自省”或“反思”的请求,实际答案是“是的,这是编译器告诉你所需信息的一种方式”。
  • @Adrian:您可能还需要解释一下您在交换机内部的情况下要做什么......
  • @MatsPetersson 我明白你在说什么,但我确实认为,当有疑问时,你需要让人们从怀疑中受益。我在 cmets 的许多答案中都说过“你真的想要 X”,但是过了某个点,人们开始觉得如果不花大量时间证明他们的需求是合理的,就不可能在 SO 上提出问题。

标签: c++ boost-fusion boost-preprocessor


【解决方案1】:

如果您使用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 in boost::fusion documentation

  2. size in boost::fusion documentation

  3. Iterating over Boost fusion::vector

【讨论】:

  • 如何生成案例陈述?我在将“2”传递给 BOOST_PP_REPEAT 并在此之上生成 case 语句时遇到问题。您能否扩展您的示例并展示它将如何在 switch 中生成 case 语句?
  • 我意识到我的 for_each 并不完全等同于你的情况,我有点跑题了。但是,您可以构造一个适当的 lambda,以便它会增加一些捕获的变量,并且仅当增量与传入的运行时变量匹配时才执行代码。
  • 感谢您的努力,但我设法完成了我需要的工作 - 添加了示例代码。
【解决方案2】:

经过长时间的搜索、阅读和找到this article。我设法将成员从 0 迭代到 count - 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 可以创建案例陈述。

【讨论】:

    猜你喜欢
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多