从 XML 中读取未指定结构的每个数据成员

Reading in each data member of an unspecified struct from XML

本文关键字:数据成员 结构 未指定 XML 读取      更新时间:2023-10-16

我有一些结构,具有不同类型和数量的数据成员:

struct Foo
{
int a;
float b;
char c;
}
struct Bar
{
std::string a;
int b;
}
struct Baz
{
char a;
}

我想用外部文件中包含的值填充这些数据成员。是否有通用解决方案,以便以后添加具有不同数据成员的新结构,则不必更改正在读取数据的代码?我更愿意保持任何独立于这些结构的功能,但目前我最好的想法是多态解决方案,其中每个结构都有一个负责读取其数据的静态方法。

C++目前还没有办法反映结构的内容。这意味着没有真正的通用方法来读取任何给定的结构(无论是按名称还是按索引(。但是,您可以创建某种元描述,这可能会导致比为每个结构重写 XML 反序列化更少的开销。

这样的元描述可能看起来像(需要C++17(:

enum FieldType { String, Int, Float, Char };
struct AbstractField
{
FieldType const type;
const char * const name;
AbstractField(FieldType type, const char *name) : type(type), name(name) {}
virtual ~AbstractField() {}
virtual bool setValue(std::any & dest, const std::any & value) const = 0;
}
template <typename Struct, typename Type>
struct Field : public AbstractField
{
Type Struct::*const fieldPtr;
Field(FieldType type, const char *name, Type Struct::*fieldPtr)
: AbstractField(type, name), fieldPtr(fieldPtr)
{}
bool setValue(std::any & dest, const std::any & value) const override
{
Struct *realDest = std::any_cast<Struct>(& dest);
const Type *realValue = std::any_cast<Type>(& value);
if (realDest != nullptr && realValue != nullptr) {
realDest->*fieldPtr = *realValue;
return true;
}
return false;
}
}
// The following has to be redone for each structure
static const std::vector<const AbstractField *> metaFoo = {
new Field<Foo, int>(Int, "a", & Foo::a)),
new Field<Foo, float>(Float, "b", & Foo::b)),
new Field<Foo, char>(Char, "c", & Foo:c))
};

可以添加一些额外的逻辑来使其更漂亮(type_id而不是枚举,仅采用名称和成员指针来创建Field实例的模板化函数,单个结构的抽象工厂等(。

然后,读取器可以在结构中设置一个值,如下所示

std::any parseValue(const std::string & value, FieldType type);
bool setField(std::any &dest, const std::vector<const AbstractField*> &meta,
const std::string & fieldName, const std::string & value)
{
for (auto field : meta) {
if (field->name == fieldName) {
std::any value = parseValue(value, field->type);
return field->setValue(dest, value);
}
}
return false;
}

当与结构的抽象工厂结合使用时(类似于我为字段所做的(,这允许仅从元描述中实例化整个结构树。