使用 boost::hana 传递反射
Passing a reflection with boost::hana
有没有办法获得一个代表 boost::hana
结构反射的对象,我可以将其传递并存储在 map/database 中?
我正在环境和作为插件动态加载的共享库之间创建一个接口。我需要反映库中使用的一些数据结构,以便用户可以在 运行 时间使用环境导航这些结构。
在一个例子中,我有这个结构,我可以很容易地反映出来:
struct Car {
BOOST_HANA_DEFINE_STRUCT(Car,
(std::string, brand),
(std::string, model)
);
};
我的图书馆将创建 Car
的实例,并且需要通过入口点使其可用。这意味着它将需要坚持从我的环境 SDK 中实现一个 base-class,它看起来有点像这样:
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 结构反射的对象,我可以将其传递并存储在 map/database 中?
----------------编辑------------
我并不真正关心取消引用数据,而是关心了解库使用的每个成员的名称、偏移量和大小。这将使我能够使用该环境根据配置在库之间映射数据,而无需在库之间共享头文件。我可能会在反射中添加类型,作为在实际执行之前验证 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;
});
直接在结构上折叠时得到的对的问题是它们包含第二部分成员的副本,这就是为什么它们不占用与实例相同的内存。
正如评论中所建议的那样,hana::accessors
折叠包含名称和函数的对,它们采用实例和 returns 对相应成员的引用。
也许这与您想要做的很接近:
#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';
}
}
有没有办法获得一个代表 boost::hana
结构反射的对象,我可以将其传递并存储在 map/database 中?
我正在环境和作为插件动态加载的共享库之间创建一个接口。我需要反映库中使用的一些数据结构,以便用户可以在 运行 时间使用环境导航这些结构。
在一个例子中,我有这个结构,我可以很容易地反映出来:
struct Car {
BOOST_HANA_DEFINE_STRUCT(Car,
(std::string, brand),
(std::string, model)
);
};
我的图书馆将创建 Car
的实例,并且需要通过入口点使其可用。这意味着它将需要坚持从我的环境 SDK 中实现一个 base-class,它看起来有点像这样:
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 结构反射的对象,我可以将其传递并存储在 map/database 中?
----------------编辑------------
我并不真正关心取消引用数据,而是关心了解库使用的每个成员的名称、偏移量和大小。这将使我能够使用该环境根据配置在库之间映射数据,而无需在库之间共享头文件。我可能会在反射中添加类型,作为在实际执行之前验证 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;
});
直接在结构上折叠时得到的对的问题是它们包含第二部分成员的副本,这就是为什么它们不占用与实例相同的内存。
正如评论中所建议的那样,hana::accessors
折叠包含名称和函数的对,它们采用实例和 returns 对相应成员的引用。
也许这与您想要做的很接近:
#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';
}
}