通过Struct和Class成员迭代

The*_*ile 27 c++ struct class

是否有可能在C++中迭代一个Struct或Class来查找它的所有成员?例如,如果我有struct a和b类:

struct a
{
  int a;
  int b;
  int c;
}

class b
{
  public:
    int a;
    int b;
  private:
    int c;
}
Run Code Online (Sandbox Code Playgroud)

是否可以循环它们以获得一个打印语句说"struct a has int named a,b,c"或"Class b has int named a,b,c"

Pau*_* II 27

有两种方法可以做到这一点,但您需要使用一些宏来定义或修改结构.

您可以使用此答案中REFLECTABLE给出的宏来定义结构,如下所示:

struct A
{
    REFLECTABLE
    (
        (int) a,
        (int) b,
        (int) c
    )
};
Run Code Online (Sandbox Code Playgroud)

然后你可以迭代字段并打印每个值,如下所示:

struct print_visitor
{
    template<class FieldData>
    void operator()(FieldData f)
    {
        std::cout << f.name() << "=" << f.get() << std::endl;
    }
};

template<class T>
void print_fields(T & x)
{
    visit_each(x, print_visitor());
}

A x;
print_fields(x);
Run Code Online (Sandbox Code Playgroud)

另一种方法是将结构调整为融合序列(参见文档).这是一个例子:

struct A
{
    int a;
    int b;
    int c;
};

BOOST_FUSION_ADAPT_STRUCT
(
    A,
    (int, a)
    (int, b)
    (int, c)
)
Run Code Online (Sandbox Code Playgroud)

然后你可以使用这个打印字段:

struct print_visitor
{
    template<class Index, class C>
    void operator()(Index, C & c)
    {

        std::cout << boost::fusion::extension::struct_member_name<C, Index::value>::call() 
                  << "=" 
                  << boost:::fusion::at<Index>(c) 
                  << std::endl;
    }
};


template<class C>
void print_fields(C & c)
{
    typedef boost::mpl::range_c<int,0, boost::fusion::result_of::size<C>::type::value> range;
    boost::mpl::for_each<range>(boost::bind<void>(print_visitor(), boost::ref(c), _1));
}
Run Code Online (Sandbox Code Playgroud)


vil*_*lla 14

不,这是不可能的,因为C++中没有反映.

  • @CaptainObvlious:答案应该回答这个问题.问题的答案是"不".我的意思是,答案可以提供一个整体机制来注释特定的结构,以便某人可以迭代表示其字段的一些数据,但仍然不迭代结构的字段,它迭代特殊配置的结构的字段. (11认同)
  • 我不确定这不是一个答案.他告诉OP关于语言限制.这就像它得到的答案一样. (10认同)
  • @willj:你的代码不是通过对问题的任何合理解释进行迭代(并且它甚至不打印提问者所要求的内容;-p).除非您可以指望使用调试信息,否则自定义反射机制仅适用于以某种方式注释的结构,而不是问题中的示例结构,而不是您自己未定义的结构. (8认同)
  • 这个问题的答案不是'不'.您可以轻松地遍历结构的成员并使用标准C++打印它们:`A a; 的printf(AA); 的printf(AB); 的printf(AC);`.使用某种自定义反射机制,有很多方法可以使语法更像所需的"循环". (3认同)
  • 多年后,我发现这个答案比选择的答案有用得多。确实,答案是否定的。是的,有一些方法可以解决并实现类似的效果,但我认为除了“极端调试”之外,不应使用任何建议。在我看来,在每个类/结构上做所有这些额外的工作在生产应用程序中会是一团糟。 (3认同)