我有一个结构
typedef struct A
{
int a;
int b;
char * c;
}aA;
我想遍历结构的每个成员并打印它的值。类似于:
void print_struct_value(struct *A)
{
for each member of struct A
cout << "struct name . member name" << "value";
}
如何在C++中做到这一点?
发布于 2013-11-30 12:55:30
有几种方法可以做到这一点,但您需要使用一些宏来定义或调整结构。
您可以使用this answer中提供的REFLECTABLE
宏来定义结构,如下所示:
struct A
{
REFLECTABLE
(
(int) a,
(int) b,
(const char *) c
)
};
然后,您可以遍历字段并打印每个值,如下所示:
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)。下面是一个例子:
struct A
{
int a;
int b;
const char * c;
};
BOOST_FUSION_ADAPT_STRUCT
(
A,
(int, a)
(int, b)
(const char *, c)
)
然后,您还可以使用以下命令打印这些字段:
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)));
}
发布于 2013-07-16 01:28:44
C++不支持开箱即用的反射,因此您所要求的在核心语言中是不可能实现的。
不同的库试图提供这样的功能,通常是通过一些方法或宏注册字段,这将在后台将字段保存到某种类型的集合中,您可以在该集合上进行迭代。
发布于 2014-07-30 05:11:42
正如@Paul所建议的,我使用带有自写for_each_member函数的BOOST_FUSION_ADAPT_STRUCT:
/**
* \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
https://stackoverflow.com/questions/17660095
复制相似问题