C++ 遍历结构和类成员
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19059157/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Iterate through Struct and Class Members
提问by Theopile
Is it possible in C++ to iterate through a Struct or Class to find all of its members? For example, if I have struct a, and class b:
是否可以在 C++ 中遍历 Struct 或 Class 以查找其所有成员?例如,如果我有 struct a 和 class b:
struct a
{
int a;
int b;
int c;
}
class b
{
public:
int a;
int b;
private:
int c;
}
Would it be possible to loop them to say get a print statement saying "Struct a has int named a, b, c" or "Class b has int named a, b, c"
是否可以循环它们说得到一个打印语句,说“结构 a 有名为 a、b、c 的 int”或“b 类有名为 a、b、c 的 int”
采纳答案by Paul Fultz II
There are a couple of ways to do this, but you need to use some macros to either define or adapt the struct.
有几种方法可以做到这一点,但您需要使用一些宏来定义或调整结构。
You can use the REFLECTABLE
macro given in this answerto define the struct like this:
您可以使用此答案中REFLECTABLE
给出的宏来定义结构,如下所示:
struct A
{
REFLECTABLE
(
(int) a,
(int) b,
(int) c
)
};
And then you can iterate over the fields and print each value like this:
然后你可以遍历这些字段并像这样打印每个值:
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);
Another way is to adapt the struct as a fusion sequence (see the documentation). Here's an example:
另一种方法是将结构调整为融合序列(请参阅文档)。下面是一个例子:
struct A
{
int a;
int b;
int c;
};
BOOST_FUSION_ADAPT_STRUCT
(
A,
(int, a)
(int, b)
(int, c)
)
Then you can print the fields as well using this:
然后你也可以使用这个打印字段:
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));
}
回答by villekulla
No, it's not possible, because there is no reflection in C++.
不,这是不可能的,因为在 C++ 中没有反射。
回答by aquirdturtle
If you have members of the same type (as you do in your first specific example) that you want to both (a) have names, and (b) be iterable, then you can combine an array with an enum:
如果您有相同类型的成员(如您在第一个特定示例中所做的那样),并且希望 (a) 具有名称,并且 (b) 是可迭代的,那么您可以将数组与枚举组合:
enum names { alice, bob, carl };
struct myStruct;
{
std::array<int, 3> members;
}
Then you can both
那么你们都可以
myStruct instance;
// iterate through them...
for (auto elem : instance.members)
{
// work with each element in sequence
}
// and call them by name, taking away the need to remember which element is the first, etc.
instance[bob] = 100;
Clearly not a general solution, but I've found this useful in my own work.
显然不是通用的解决方案,但我发现这在我自己的工作中很有用。
回答by QCTDev
Provided your member variables are of the same type, you can do something like this that i stole from the GLM library:
如果您的成员变量类型相同,您可以执行我从 GLM 库中窃取的类似操作:
class Point
{
Point();// you must re-implement the default constructor if you need one
union
{
struct
{
double x;
double y;
double z;
}
std::array<double, 3> components;
}
}
Admittedly this isn't the most elegant solution from a maintainability standpoint, manually keeping count of the number of variables you have is asking for trouble. However It will work without additional libraries or macros and is applicable in most situations that you'd want this behaviour.
诚然,从可维护性的角度来看,这不是最优雅的解决方案,手动计算您拥有的变量数量会带来麻烦。但是,它无需额外的库或宏即可工作,并且适用于您希望这种行为的大多数情况。
Unions don't support automatically generated default constructors so you'll need to write one that tells the object how to initialise the union.
联合不支持自动生成的默认构造函数,因此您需要编写一个告诉对象如何初始化联合的构造函数。
for (double component : point.components)
{
// do something
}