有没有办法让一个对象代表boost::hana
结构反射,我可以传递并存储在地图/数据库中?
我正在创建环境和共享库之间的接口,这些库作为插件动态加载。我需要反映库中使用的一些数据结构,以便用户可以在运行时使用环境来导航这些结构。
在一个例子中,我有这个结构,我可以很容易地反映出来:
struct Car {
BOOST_HANA_DEFINE_STRUCT(Car,
(std::string, brand),
(std::string, model)
);
};
我的库将创建Car
的实例,并且需要通过入口点使其可用。这意味着它需要坚持从我的环境SDK实现一个基类,看起来像这样:
template<class SharedStructureType>
class LibraryAPI
{
public:
virtual void run() = 0; // Some entrypoint called by the environment
ReflectedType GetReflection()
{
return to_reflection(m_sharedData);
}
protected:
SharedStructureType m_sharedData;
private:
ReflectedType to_reflection(SharedStructureType);
};
我的问题是我不确定如何实施LibraryAPI::to_reflection
。
当一个结构被boost :: hana反映时,我希望看到一些代表反射规则的对象或成员,这就是我希望通过界面传递的内容。但是,调试器显示没有这样的东西。
我怀疑它在编译时解决的巨型模板中都得到了解决。但是,我的环境和库不会同时编译,因此这会使事情变得更复杂。
有没有办法让一个对象代表一个boost :: hana结构反射,我可以传递并存储在地图/数据库中?
--------------- -----------编辑
我并不关心取消引用数据,因为我非常关心知道库使用的每个成员的名称,偏移量和大小。这将让我使用环境基于配置在库之间映射数据,而无需在库之间共享头文件。我可能会在反射中添加类型作为在实际执行之前验证memcpy的方法。
不幸的是,在这种情况下,bmw.brand
和boost::hana::second(pair)
在调试器中运行时不会占用相同的内存。
Car bmw{"BMW", "Z3"};
boost::hana::for_each(bmw, [&](auto pair) {
if(&bmw.brand == &boost::hana::second(pair)
// We never get here
int i;
});
答案 0 :(得分:1)
在结构上直接折叠时得到的对的问题是它们包含第二部分中成员的副本,这就是为什么它们不占用与实例相同的内存。
正如评论hana::accessors
中所建议的那样,使用包含名称和函数的对进行折叠,获取实例并返回对相应成员的引用。
也许这与你想要做的很接近:
#include <array>
#include <boost/hana.hpp>
#include <iostream>
#include <string>
#include <vector>
namespace hana = boost::hana;
struct Car {
BOOST_HANA_DEFINE_STRUCT(Car,
(std::string, brand),
(std::string, model),
(std::array<char, 4>, year)
);
};
struct member_meta
{
std::string name;
std::size_t offset;
std::size_t size;
};
int main() {
Car bmw{"BMW", "Z3", {'2', '0', '1', '0'}};
std::vector<member_meta> bmw_meta{};
hana::for_each(hana::accessors<Car>(), [&](auto pair)
{
bmw_meta.push_back(member_meta{
std::string(hana::to<char const*>(hana::first(pair)))
, reinterpret_cast<size_t>(&hana::second(pair)(bmw)) - reinterpret_cast<size_t>(&bmw)
, sizeof(hana::second(pair)(bmw))
});
});
for (auto const& x : bmw_meta)
{
std::cout << x.name << ' ' << x.offset << ' ' << x.size << '\n';
}
}