C++ 模板参数包序列化
我需要创建一个模块化序列化程序。我正在使用msgpack 因此,一个简单的表单如下所示:C++ 模板参数包序列化,c++,C++,我需要创建一个模块化序列化程序。我正在使用msgpack 因此,一个简单的表单如下所示: enum class FieldId { Time, Pressure }; struct TimeFieldConfig { typedef long long DataType; const static FieldId id = FieldId::Time; } struct PressureFieldConfig { typedef double DataType; co
enum class FieldId
{
Time,
Pressure
};
struct TimeFieldConfig
{
typedef long long DataType;
const static FieldId id = FieldId::Time;
}
struct PressureFieldConfig
{
typedef double DataType;
const static FieldId id = FieldId::Pressure;
}
struct BaseField
{
virtual void dump(std::ofstream &buffer) const = 0;
};
template<class T>
struct Field : BaseField
{
void dump(std::ofstream &buffer)
{
msgpack::pack(buffer, values);
}
std::vector<typename T::DataType> values;
}
struct Recorder
{
template <class T>
void insertField()
{
data.insert_or_assign(T::id, new Field<T>);
}
template <class T>
void add(const typename T::DataType &v)
{
if (data.find(T::id) != data.cend())
reinterpret_cast<Field<T> *>(data[T::id])->add(v);
}
void dump(const std::string fpath)
{
std::ofstream outFile;
outFile.open(fpath, std::ios::binary);
// headers
std::vector<int> keys;
for (const auto &k : data)
keys.push_back(static_cast<int>(k.first));
msgpack::pack(outFile, keys);
// values
for (const auto &k : data)
k.second->dump(outFile);
outFile.close();
}
std::map<FieldId, BaseField *> data;
}
int main(int arc, char* argv[])
{
Recorder r;
r.insertField<TimeFieldConfig>();
r.insertField<PressureFieldConfig>();
/* add data ... */
r.dump("data.dat");
}
枚举类字段ID
{
时间
压力
};
结构TimeFieldConfig
{
typedef长数据类型;
const static FieldId=FieldId::Time;
}
结构压力场配置
{
typedef双数据类型;
常量静态字段id=字段id::压力;
}
结构基场
{
虚拟空转储(流和缓冲区的std::of)常量=0;
};
模板
结构字段:基本字段
{
无效转储(流和缓冲区的标准::)
{
msgpack::pack(缓冲区、值);
}
std::向量值;
}
结构记录器
{
模板
void insertField()
{
插入或赋值(T::id,新字段);
}
模板
void add(const typename T::DataType&v)
{
if(data.find(T::id)!=data.cend())
重新解释(数据[T::id])->添加(v);
}
无效转储(const std::string fpath)
{
std::出流管;
open(fpath,std::ios::binary);
//标题
向量键;
用于(常量自动和k:数据)
键。向后推(静态施法(k.first));
msgpack::pack(输出文件、密钥);
//价值观
用于(常量自动和k:数据)
k、 第二->转储(输出文件);
outFile.close();
}
地图数据;
}
int main(int弧,字符*argv[]
{
记录器r;
r、 insertField();
r、 insertField();
/*添加数据*/
r、 转储(“data.dat”);
}
转储工作正常,所有数据和标题都存在。
现在我想加载回记录的数据
我的问题是如何创建一个动态插入所需字段的
记录器的实例 我自己回答,以防有帮助
我想要创建的是命名为注册表模式。
我就是这样做的
// may be a singleton
class FieldFactory
{
public:
FieldFactory()
{
}
~FieldFactory()
{
}
template <class T>
void registerField()
{
creators.insert_or_assign(T::id, &Field<T>::creator);
}
BaseField *create(FieldId fid)
{
return creators[fid]();
}
private:
typedef std::function<BaseField *()> FieldCreator;
std::map<FieldId, FieldCreator> creators;
};
我想可能会有所改进,但这就是我的想法。这太宽泛了-你已经尝试过什么?你在哪里卡住了?
FieldFactory ff;
ff.registerField<TimeFieldConfig>();
ff.registerField<PressureFieldConfig>();
static BaseField *creator()
{
return new Field<T>();
}
void reload(const std::string &filePath)
{
std::ifstream inFile;
inFile.open(filePath, std::ios::binary);
std::vector<char> buffer((std::istreambuf_iterator<char>(inFile)), (std::istreambuf_iterator<char>()));
inFile.close();
// headers
std::size_t off = 0;
std::vector<int> keys;
msgpack::object_handle result;
msgpack::unpack(result, buffer.data(), buffer.size(), off);
result.get().convert(keys);
// create fields
for (auto k : keys)
{
FieldId fid = static_cast<FieldId>(k);
data.insert_or_assign(fid, m_ff->create(fid));
}
// values
for (auto k : keys)
{
msgpack::object_handle oh;
msgpack::unpack(oh, buffer.data(), buffer.size(), off);
FieldId fid = static_cast<FieldId>(k);
if (data.find(fid) != data.cend())
data[fid]->reload(oh);
}
}