说我有一个类/结构如下:

struct A {
    uint32_t a;
    uint8_t  b;
    uint16_t c;
};

我有一组与A的每个成员相关的字符串(可以是不同的整数类型,但不能是非整数类型,例如字符串),例如
"field1" -> A::a
"field2" -> A::b
"field3" -> A::c

假设字符串和成员之间始终存在1:1映射。有没有一种优雅的方法可以使用std::unordered_map这样的方式将每个字符串映射到每个成员?
我希望能够使用字符串作为键来读取和写入每个字段,例如
A a {1,2,3};
mymap["field1"] = 4; // a.a = 4
mymap["field2"] = 5; // a.b = 5
auto c = mymap["field3"]; // c = a.c = 3

我正在使用C++ 11/14,不能使用boost。

有关此问题的上下文的更多信息:
问题中提到的struct A是程序的设置。它们是硬件配置参数,我的软件程序用于模拟硬件行为。这些设置/配置是如上所述的脚本生成的struct。我们读/写这些struct成员,并且由于这些设置/配置的数量如此之多(数千个),因此也能够方便地按其名称访问它们。这就是为什么&为什么我要将每个成员与一个字符串相关联。下标还是访问相应成员的函数并不重要,但是字符串(设置的名称)与生成的struct成员之间存在这样的1:1映射。正如我在问题中提到的那样,这些成员属于不同的整数类型。

最佳答案

您可以创建一个环绕整数的代理类,然后将该代理类存储在std::unordered_map中。

#include <iostream>
#include <functional>
#include <unordered_map>

struct A {
    uint32_t a;
    uint8_t  b;
    uint16_t c;
};

struct ValueWrapper {
    using value_type = uint64_t;

    template <typename Obj, typename T>
    ValueWrapper(Obj& obj, T Obj::*member) {
        get = [&, member]() { return obj.*member; };
        set = [&, member](value_type value) mutable { obj.*member = value; };
    }

    ValueWrapper()  = default;

    ValueWrapper& operator=(value_type value) {
        set(value);
        return *this;
    }

    operator value_type() {
        return get();
    }

    std::function<value_type()> get;
    std::function<void(value_type)> set;
};

std::unordered_map<std::string, ValueWrapper> make_map(A& a) {
    std::unordered_map<std::string, ValueWrapper> map;

    map["field1"] = ValueWrapper(a, &A::a);
    map["field2"] = ValueWrapper(a, &A::b);
    map["field3"] = ValueWrapper(a, &A::c);

    return map;
}

int main() {
    A a{1,2,3};

    auto map = make_map(a);

    map["field2"] = 67;

    std::cout << a.a << " " << static_cast<int>(a.b) << " " << a.c << std::endl;
    std::cout <<  map["field1"] << " " <<  map["field2"] << " " <<  map["field3"] << std::endl;
}

您确实有一些限制,具体取决于value_type。如果您使用int64_t,则可以安全地包装除uint64_t之外的任何内容。如果您使用uint64_t,则可以包装所有无符号整数,但不能安全地包装有符号整数。

我将默认构造函数放在那里,以满足unordered_mapoperator[]的使用。

08-06 00:23
查看更多