我想逐步浏览C ++结构的成员并打印出它们的值。我可以很容易地明确地对此进行编码,但有没有办法在不知道结构中有什么的情况下这样做呢?
我想我正在寻找C ++等同于C#的foreach命令。
感谢您的帮助。
ADD:我在C#中正在做这样的事情。此代码从先前读取的XML文件中设置struct成员:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct SettingsStruct
{
public uint nLength;
}
private void UpdateSettings()
{
SettingsStruct settings = new SettingsStruct();
foreach (FieldInfo fieldInfo in typeof(SettingsStruct).GetFields())
{
string settingName = "SETTING." + fieldInfo.Name.ToUpper();
if (appSettings.Contains(settingName))
{
switch (fieldInfo.FieldType.FullName)
{
case "System.UInt32":
fieldInfo.SetValueDirect(__makeref(settings), uint.Parse((string)appSettings[settingName]));
break;
}
}
}
}
答案 0 :(得分:4)
如果您愿意使用boost fusion,您可以这样做。首先将此结构“推广”为融合序列,然后您可以遍历序列打印出每个成员。
答案 1 :(得分:2)
你可以为你的结构重载operator<<
,然后你只需要编写一次代码。
答案 2 :(得分:2)
以下Stackoverflow答案可以让您了解您正在寻找的内容
Iterate Over Struct; Easily Display Struct Fields And Values In a RichEdit Box
答案 3 :(得分:1)
不敢。 C ++提供有限的反射能力。 RTTI C ++系统允许您访问类型,但不对该类型中的字段进行内省。
使用一些宏魔法/ hackery你可以实现这一点,请参阅Reflection for C++以获取示例。
答案 4 :(得分:1)
foreach命令不会在C#中执行您所说的操作。 foreach遍历集合的元素(数组,集合,列表......)而不是结构的成员(比如“length”......)。
C ++中foreach的等价物是使用迭代器(xs.begin(),xs.end())。您可以使用BOOST_FOREACH语法更清晰(或者在C ++ 1x中使用(X&amp; s:xs))。
答案 5 :(得分:1)
C ++不允许对一般类成员进行迭代。但是,如果您准备接受某些限制,并使用某些人认为是纯粹邪恶的技术,您可以设置一个框架以允许迭代特定类类别的成员。这是通过滥用默认赋值运算符递归地应用于类的所有成员这一事实来实现的。
首先,我们需要声明要包含在迭代中的类型:
struct Visitable1;
struct Visitable2;
struct Visitable3;
我们还需要一个抽象基类来进行迭代操作(为了简洁省略了析构函数;为安全起见,它应该是虚拟的或受保护的):
struct Visitor
{
virtual void visit(Visitable1 &) = 0;
virtual void visit(Visitable2 &) = 0;
virtual void visit(Visitable3 &) = 0;
static Visitor * current;
};
和一个基类(使用“奇怪的递归模板”成语)我们可以包含在迭代中的类型;这是操作员滥用发生的地方,修改了自我分配的行为:
template <typename T>
struct Visitable
{
void operator=(Visitable const & other)
{
if (&other == this) {
Visitor::current->visit(static_cast<T&>(*this));
}
}
};
struct Visitable1 : Visitable<Visitable1> { /* some stuff */ };
struct Visitable2 : Visitable<Visitable2> { /* some stuff */ };
struct Visitable3 : Visitable<Visitable3> { /* some stuff */ };
最后,我们可以定义迭代本身:
template <class T, class Visitor>
void for_each(T & t, Visitor v)
{
Visitor::current = &v;
t = t;
}
这确实有一些明显的缺点:
Visitor::current
)意味着任何时候只能进行一次迭代,从而产生线程安全和重入问题。我目前无法想到将状态传递给operator=
的更好方法,因为这仅在重载默认operator=
时才有效,并且使用与受让人相同类型的单个参数。请参阅codepad.org进行演示。