映射类的数据成员
Mapping data members of a class
我正在尝试设计一个数据结构,它将通过存储一些关于其成员的额外数据来增强/补充现有的结构。
假设我们有:
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_STRUCT来定义可以使用for_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
,每个类一个。每个成员都由其从其封闭类的开头开始的偏移量来标识。
通常,您将宏用于此类目的。他们可以生成您想要的任何类型的代码/包装器,让您拥有对数据的通常访问权限,还可以添加您想要/需要的东西。它不漂亮,但它有效。
有一些模板库可以在这里提供帮助,例如Boost.Fusion或Boost.Hana,但是,如果您不使用其高级功能(带有长编译价格标签(,您也可以在此处推出自己的模板库。
此外,如果您可以专注于特定的 GUI 框架,它们对这些东西有一些支持。例如,Qt有自己的"元对象"编译器。
你可以试试这个模板吗? 例如
template <typename T>
class GuiItem : public T {
map<MemberHandle, GuiElement*> guiHandles;
}
GuiItem<A> guiA;
guiA.x = 123;
guiA.y = "y";
guiA.guiHandles[handle] = element;
我不确定我是否了解其他要求,因此这种方式可能不适合您。
- 用于访问容器<T>数据成员的正确 API
- 将函数类成员映射到类本身内部
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 数据成员SFINAE的C++17测试:gcc vs clang
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 如何在c++中定义以struct为数据成员的类中的构造函数
- 静态数据成员模板专用化的实例化点在哪里
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 使用指针访问数组中的对象数据成员
- 友元函数无法访问私有数据成员 (c++)
- 我可以在 C++ 中将数据成员/变量从其定义之外添加到结构中吗?
- 为什么将一个结构的引用设置为等于另一个结构只会更改一个数据成员?
- 将私有数据成员添加到野牛生成的类中
- 输入数据成员未按要求工作
- 二维矢量数据成员
- 在类 A 中创建类型为 B 类的向量 - 访问数据 [C++] [成员在两个类中都是私有的]
- 调用在 HXX 文件中声明的静态数据成员
- 是否可以根据其数据成员的类型确定类型的大小
- 访问数据成员(本身是对象)的数据成员,就好像它们是类成员一样
- 映射类的数据成员