首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >迭代C++中的结构

迭代C++中的结构
EN

Stack Overflow用户
提问于 2013-07-16 01:23:41
回答 5查看 68.5K关注 0票数 56

我有一个结构

代码语言:javascript
复制
typedef struct A
{
    int a;
    int b;
    char * c;
}aA;

我想遍历结构的每个成员并打印它的值。类似于:

代码语言:javascript
复制
void print_struct_value(struct *A)
{
    for each member of struct A
    cout << "struct name . member name" << "value";
}

如何在C++中做到这一点?

EN

回答 5

Stack Overflow用户

发布于 2013-11-30 12:55:30

有几种方法可以做到这一点,但您需要使用一些宏来定义或调整结构。

您可以使用this answer中提供的REFLECTABLE宏来定义结构,如下所示:

代码语言:javascript
复制
struct A
{
    REFLECTABLE
    (
        (int) a,
        (int) b,
        (const char *) c
    )
};

然后,您可以遍历字段并打印每个值,如下所示:

代码语言:javascript
复制
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);

另一种方法是将结构调整为融合序列(参见the documentation)。下面是一个例子:

代码语言:javascript
复制
struct A
{
    int a;
    int b;
    const char * c;
};

BOOST_FUSION_ADAPT_STRUCT
(
    A,
    (int, a)
    (int, b)
    (const char *, c)
)

然后,您还可以使用以下命令打印这些字段:

代码语言:javascript
复制
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(), _1, boost::ref(c)));
}
票数 21
EN

Stack Overflow用户

发布于 2013-07-16 01:28:44

C++不支持开箱即用的反射,因此您所要求的在核心语言中是不可能实现的。

不同的库试图提供这样的功能,通常是通过一些方法或宏注册字段,这将在后台将字段保存到某种类型的集合中,您可以在该集合上进行迭代。

票数 15
EN

Stack Overflow用户

发布于 2014-07-30 05:11:42

正如@Paul所建议的,我使用带有自写for_each_member函数的BOOST_FUSION_ADAPT_STRUCT:

代码语言:javascript
复制
/**
 * \brief Allows iteration on member name and values of a Fusion adapted struct.
 * 
 *  
 * BOOST_FUSION_ADAPT_STRUCT(ns::point,
 *      (int, x)
 *      (int, y)
 *      (int, z));
 *
 * template<class T>
 * print_name_and_value(const char* name, T& value) const {
 *    std::cout << name << "=" << value << std::endl;
 * } 
 *
 * 
 * int main(void) {
 *  
 *  ns::point mypoint;
 *
 *  
 *      boost::fusion::for_each_member(mypoint, &print_name_and_value);
 *
 *
 * }
 *
 */
#ifndef BOOST_FUSION_FOR_EACH_MEMBER_HPP
#define BOOST_FUSION_FOR_EACH_MEMBER_HPP

#include <functional>

#include <boost/fusion/include/adapt_struct.hpp>

#include <boost/fusion/sequence/intrinsic/begin.hpp>
#include <boost/fusion/sequence/intrinsic/end.hpp>
#include <boost/fusion/sequence/intrinsic/front.hpp>
#include <boost/fusion/iterator/equal_to.hpp>
#include <boost/fusion/iterator/next.hpp>
#include <boost/fusion/iterator/deref.hpp>
#include <boost/fusion/iterator/distance.hpp>
#include <boost/fusion/support/category_of.hpp>
#include <boost/mpl/bool.hpp>

namespace boost { namespace fusion {

namespace detail {

  template <typename First, typename Last, typename F>
  inline void
  for_each_member_linear(First const& first,
      Last const& last,
      F const& f,
      boost::mpl::true_) {}

  template <typename First, typename Last, typename F>
  inline void
  for_each_member_linear(First const& first,
      Last const& last,
      F const& f,
      boost::mpl::false_) {

      f(
                extension::struct_member_name<
                    typename First::seq_type, First::index::value
                >::call(),
                *first
            );

      for_each_member_linear(
          next(first),
          last,
          f,
          result_of::equal_to< typename result_of::next<First>::type, Last>()
      );
  }

  template <typename Sequence, typename F>
  inline void
  for_each_member(Sequence& seq, F const& f) {

    detail::for_each_member_linear(
      fusion::begin(seq),
      fusion::end(seq),
      f,
      result_of::equal_to<
        typename result_of::begin<Sequence>::type,
        typename result_of::end<Sequence>::type>()
    );
  }

}

  template <typename Sequence, typename F>
  inline void
  for_each_member(Sequence& seq, F f) {
    detail::for_each_member(seq, f);
  }

}}

#endif 
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17660095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档