说我有一个类/结构如下:
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_map
对operator[]
的使用。