c++ - C++ Cereal:如何在不知道其 polymorphic_id 的情况下加载多态类?
问题描述
我想执行名称和参数存储在 XML 文件中的 c++ 函数列表。因此,我将所有函数都放在派生类中,这样一旦设置了对象,我就可以run
关联函数。因此,现在的问题是将我的 XML 文件反序列化为基类的多态指针。
这是能够将 XML 类反序列化为多态指针的Cereal
库(我很幸运)。为此,该库需要 XML 文件中的额外关键字。所以,我必须对我的 XML 文件进行后处理以使其兼容。这不是我喜欢或想要的东西,但好吧,让我们去做吧。
不幸的是,这里开始我的问题。需要的额外关键字之一Cereal
是一个名为 的变量polymorphic_id
,我事先并不知道这个变量(或者可能会随着时间而改变)。更准确地说,这是一个由(可能通过子例程)polymorphic_id
生成的内部变量,所以我寻找一种方法来访问这些内部变量,以便在我的函数名称和它们的. 或解决此预处理步骤的另一种方法。Cereal
CEREAL_REGISTER_TYPE
polymorphic_id
这是改编自Cereal 文档的 MWE :
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <cereal/archives/xml.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/polymorphic.hpp>
using namespace std;
class SuperParentClass
{
private:
/* data */
public:
virtual std::string get_nameClass() =0;
virtual int run() = 0;
void serialize() ;
};
class ClassRectangle : public SuperParentClass
{
private:
/* data */
public:
std::string get_nameClass(){return "Rectangle";};
double length=0.;
double width=0.;
vector<double> center={0., 2.};
template <class Archive>
void serialize( Archive & ar )
{
ar( CEREAL_NVP( length ) );
ar( CEREAL_NVP( width ) );
ar( CEREAL_NVP( center ) );
}
int run()
{
std::cout << "I am a Rectangle with length "<<length << std::endl;
return 0;
}
};
CEREAL_REGISTER_TYPE(ClassRectangle);
CEREAL_REGISTER_POLYMORPHIC_RELATION(SuperParentClass, ClassRectangle)
class ClassCircle : public ClassRectangle
{
private:
/* data */
public:
std::string get_nameClass(){return "Circle";};
double radius=0.;
vector<double> center={0., 2.};
template <class Archive>
void serialize( Archive & ar )
{
ar( CEREAL_NVP( radius ) );
ar( CEREAL_NVP( center ) );
}
int run()
{
std::cout << "I am a Cricle with radius "<<radius << std::endl;
return 0;
}
};
CEREAL_REGISTER_TYPE(ClassCircle);
CEREAL_REGISTER_POLYMORPHIC_RELATION(ClassRectangle, ClassCircle)
int main(void)
{
// Beginning of main.
cout << "(Start)" << endl;
// Save Part.
{
cout << "SAve " << endl;
std::shared_ptr<SuperParentClass> Shape = std::make_shared<ClassRectangle>();
std::ofstream outs("Input_1.xml");
cereal::XMLOutputArchive archive( std::cout ); //( outs ) ;// ( std::cout ); //
archive( cereal::make_nvp(Shape->get_nameClass(), Shape) );
Shape = std::make_shared<ClassCircle>();
archive( cereal::make_nvp(Shape->get_nameClass(), Shape) );
}
// Load Part.
cout << "Load " << endl;
std::ifstream is("Input_2.xml"); // NEEDS TO BE REPLACE BY "Input1.xml"
cereal::XMLInputArchive arr(is);
std::shared_ptr<SuperParentClass> ShapeBis;
arr( cereal::make_nvp("Rectangle", ShapeBis) );
ShapeBis->run();
arr( ShapeBis );
ShapeBis->run();
// End of the main.
cout << "(End) " << endl;
return 0;
}
// EoF
在这个 MWE 中,该文件Input_2.xml
是我拥有的 XML 文件,我应该后处理:
<?xml version="1.0"?>
<Rectangle>
<length>2.3</length>
<width>0</width>
<center size="dynamic">
<value0>0</value0>
<value1>1</value1>
</center>
</Rectangle>
<Circle>
<radius>10.</radius>
<center size="dynamic">
<value0>1</value0>
<value1>1</value1>
</center>
</Circle>
而文件Input_1.xml
是序列化的结果,是我在Input_2.xml
.
Input_1.xml
:
<?xml version="1.0" encoding="utf-8"?>
<cereal>
<Rectangle>
<polymorphic_id>2147483649</polymorphic_id>
<polymorphic_name>ClassRectangle</polymorphic_name>
<ptr_wrapper>
<id>2147483649</id>
<data>
<length>22.3</length>
<width>0</width>
<center size="dynamic">
<value0>0</value0>
<value1>2</value1>
</center>
</data>
</ptr_wrapper>
</Rectangle>
<Circle>
<polymorphic_id>2147483660</polymorphic_id>
<polymorphic_name>ClassCircle</polymorphic_name>
<ptr_wrapper>
<id>2147483660</id>
<data>
<radius>10.</radius>
<center size="dynamic">
<value0>1</value0>
<value1>1</value1>
</center>
</data>
</ptr_wrapper>
</Circle>
</cereal>
那么如何在不知道其 polymorphic_id 的情况下使用 Cereal 加载多态类呢?或者换句话说,如何在内部 polymorphic_id 和我的类名之间创建映射?
解决方案
推荐阅读
- php - Laravel 商店用户 ip
- ruby-on-rails - Rails、事务性电子邮件和发件人验证
- mongodb - 如何替换以下 2 个命令以使用 BSON 文件?
- c# - c#如何获取最后一个div元素?
- or-tools - Or-tools 路由节点与索引
- python-3.x - 如何在 conda 中创建具有多个通道的环境
- r - 仅在开始输入 R Shinyapp 时才显示下拉菜单
- google-cloud-platform - GCR (Google Cloud Run) 启用 http
- c - bash:./remoteServer .o:无法执行二进制文件:执行格式错误
- c# - 在 List 的派生类上设置属性
在运行时使用反射实例化