c++ - 映射类的数据成员
问题描述
我正在尝试设计一种数据结构,它可以通过存储一些关于其成员的额外数据来增强/补充现有的数据结构。
假设我们有:
class A {
int x;
string y;
};
我们希望有一个与之关联的 GUI 组件,因此数据成员具有相应的 GUI 元素。我想将成员映射到各自的组件。就像是
class GuiA {
int x;
string y;
map<MemberHandle, GuiElement*> guiHandles;
}
我没有任何限制,但我希望结果可以轻松转换为原始类型。
我知道,我可以引入一个模板,例如GuiElementMember
保存原始数据和GuiElement
指针,并将类成员交换为装饰的对应对象,所以它看起来像:
class GuiA {
GuiElementMember<int> x;
GuiElementMember<string> y;
}
但我想避免它,因为它完全改变了对数据成员的访问模式并使其膨胀。即它的结果是数据成员与指针交错,不容易去除。
理想情况下,可以写成GuiA
的派生类A
,或者写成 的组合A
和附加的东西。
我正在考虑类可以生成地图的模板之类的东西。我可以为每个组件编写一个自定义类,但我认为没有一种简单的方法来映射数据成员,所以在客户端它看起来像getGuiMember(GuiA::x)
. 指向数据成员的指针包含成员原始类型。我认为不可能有像“类型擦除的成员指针”这样可以用作MemberHandle
类型的东西。
我想到的唯一一件事是enum
每个组件的自定义,它将枚举数据成员并用作地图(或本例中的向量)的键类型,但这似乎是大量的信息复制和维护。
是否有一些允许映射数据成员的技术?
只要接口简单,我并不真正关心实现的复杂性。我欢迎提升或模板魔术。我也不关心额外数据访问的性能,它是额外的东西,但普通类的使用不应该受到影响,因此引入无法优化的间接性不太受欢迎。
编辑:请不要依赖 GUI 的东西,这是一个例子。我只关心为每个成员存储一些额外的数据,而不是与成员一起组成。
解决方案
您可以使用BOOST_FUSION_DEFINE_STRUCTfor_each
定义可以通过循环迭代的结构:
#include <boost/fusion/include/define_struct.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <unordered_map>
#include <string>
#include <cstdint>
BOOST_FUSION_DEFINE_STRUCT(
(demo), employee,
(std::string, name)
(int, age)
)
struct GuiElement;
GuiElement* createGuiElement(char const* name);
using Mapping = std::unordered_map<size_t, GuiElement*>;
template<class T>
Mapping create_mapping(T&& t) {
Mapping mapping;
boost::fusion::for_each(t, [&](auto& member) {
auto offset = reinterpret_cast<uintptr_t>(&member) - reinterpret_cast<uintptr_t>(&t);
mapping[offset];
});
return mapping;
}
template<class T, class M>
GuiElement*& get_mapping_element(Mapping& mapping, T const& t, M const& member) {
auto offset = reinterpret_cast<uintptr_t>(&member) - reinterpret_cast<uintptr_t>(&t);
auto found = mapping.find(offset);
if(found == mapping.end())
std::abort();
return found->second;
}
int main() {
auto employee_mapping = create_mapping(demo::employee{});
demo::employee e1;
get_mapping_element(employee_mapping, e1, e1.name) = createGuiElement("name");
get_mapping_element(employee_mapping, e1, e1.age) = createGuiElement("age");
}
在代码中有一个Mapping
, 每个类一个。每个成员都由其与其封闭类开头的偏移量来标识。
推荐阅读
- java - 使用 jira api 获取 org.codehaus.jettison.json.JSONException 时面临问题:缺少值。在性格
- node.js - 无法使用 ReactJs 从托管在 localhost 上的 node.js API 获取数据
- python - If 语句无法解析余数:'|' 从'|"
- amazon-web-services - 如何从 CloudFormation 模板中的 S3 链接下载 lambda 代码
- ios - Xcode中以下两个网络扩展选项有什么区别
- authentication - 在客户端存储客户端机密
- java - 如何从mysql获取多行
- python - 如何从 xarray 数据集坐标创建变量?
- c# - 如何在使用 OAuthPrompt 时在 BOT 中启用多个 AD 身份验证,或者可以使用哪些其他机制来启用多个 AD?
- angular - 使用 *ngIf 进行 Mat-select 导致 ExpressionChangedAfterItHasBeenCheckedError