C++ 从XML读入未指定结构的每个数据成员

C++ 从XML读入未指定结构的每个数据成员,c++,C++,我有一些数据成员类型和数量不同的结构: struct Foo { int a; float b; char c; } struct Bar { std::string a; int b; } struct Baz { char a; } 我想用外部文件中包含的值填充这些数据成员。有没有一个通用的解决方案,如果我以后添加一个具有不同数据成员的新结构,我就不必修改读取数据的代码?我更愿意让任何功能独立于这些结构,但目前我最好的想法是一个多态解决方

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

struct Foo
{
    int a;
    float b;
    char c;
}

struct Bar
{
    std::string a;
    int b;
}

struct Baz
{
    char a;
}

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

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

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


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

您不能使用静态成员,因为
将不可用。我已经使用XML很长时间了,它对读写成员非常有效。我有使用
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))
};
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;
}