如何使用带有嵌套结构和最少代码更改的 boost::serialization ?

2024-04-10

目前我们使用存储在嵌套结构中的 POD。例子:

#define MaxNum1 100;
#define MaxNum2 50;

struct A
{
    int Value[MaxNum1]; 
    char SomeChar = 'a';
};

struct B
{
    A data[MaxNum2];
    float SomeFloat = 0.1f;
};


int main()
{
    B StructBObject = {};
}

我们希望使用 std::vector 增强我们的数据结构,如下所示:

struct NewA
{
    std::vector<int> Value; 
    char SomeChar = 'a';
};

struct NewB
{
    std::vector<NewA> data;
    float SomeFloat = 0.1f;
};

int main()
{
    NewB StructNewBObject = {};
}

反对这一修改的唯一论点是NewA and NewB不再是 POD,这使得读/写文件变得更加复杂。

怎么可能读/写NewA and NewB到一个文件使用boost::serialization以最小的 代码更改为NewA and NewB?最少的代码更改很重要,因为我们使用例如最多有 7 个嵌套级别的大结构。


您可以使用 boost 序列化进行序列化:

template <typename Ar> void serialize(Ar& ar, A& a, unsigned) {
    ar & a.Value & a.SomeChar;
}
template <typename Ar> void serialize(Ar& ar, B& b, unsigned) {
    ar & b.data & b.SomeFloat;
}

使用这些,你将already使用 C 数组和 std::vector 方法都具有开箱即用的正确行为。

如果您想继续使用固定大小的可简单复制类型²,您可以使用 Boost Container 之类的东西static_vector:它将跟踪当前大小,但数据是在结构内部静态分配的。

三重演示

这是一个三重演示程序,具有三种实现,具体取决于IMPL多变的。

正如您所看到的,大部分代码保持不变。然而,为了“最佳比较”,我确保所有容器在序列化之前都处于一半容量(50/25)。

主程序也反序列化。

Live On Coliru http://coliru.stacked-crooked.com/a/4c7d57a4a6d56d64

#include <boost/iostreams/device/back_inserter.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>

#include <boost/serialization/access.hpp>
#include <boost/serialization/is_bitwise_serializable.hpp>
#include <boost/serialization/binary_object.hpp>

#include <iostream>

#if (IMPL==0) // C arrays
    struct A {
        int Value[100]; 
        char SomeChar = 'a';
    };

    struct B {
        A data[50];
        float SomeFloat = 0.1f;
    };

    template <typename Ar> void serialize(Ar& ar, A& a, unsigned) {
        ar & a.Value & a.SomeChar;
    }
    template <typename Ar> void serialize(Ar& ar, B& b, unsigned) {
        ar & b.data & b.SomeFloat;
    }

#elif (IMPL==1) // std::vector
    #include <boost/serialization/vector.hpp>
    struct A {
        std::vector<int> Value;
        char SomeChar = 'a';
    };

    struct B {
        std::vector<A> data;
        float SomeFloat = 0.1f;
    };

    template <typename Ar> void serialize(Ar& ar, A& a, unsigned) {
        ar & a.Value & a.SomeChar;
    }
    template <typename Ar> void serialize(Ar& ar, B& b, unsigned) {
        ar & b.data & b.SomeFloat;
    }

#elif (IMPL==2) // static_vector
    #include <boost/serialization/vector.hpp>
    #include <boost/container/static_vector.hpp>
    struct A {
        boost::container::static_vector<int, 100> Value; 
        char SomeChar = 'a';
    };

    struct B {
        boost::container::static_vector<A, 50> data; 
        float SomeFloat = 0.1f;
    };

    template <typename Ar> void serialize(Ar& ar, A& a, unsigned) {
        ar & boost::serialization::make_array(a.Value.data(), a.Value.size()) & a.SomeChar;
    }
    template <typename Ar> void serialize(Ar& ar, B& b, unsigned) {
        ar & boost::serialization::make_array(b.data.data(), b.data.size()) & b.SomeFloat;
    }

#endif

namespace bio = boost::iostreams;
static constexpr auto flags = boost::archive::archive_flags::no_header;
using BinaryData = std::vector</*unsigned*/ char>;

int main() {
    char const* impls[] = {"C style arrays", "std::vector", "static_vector"};
    std::cout << "Using " << impls[IMPL] << " implementation: ";
    BinaryData serialized_data;

    {
        B object = {};
#if IMPL>0
        {
            // makes sure all containers half-full
            A element;
            element.Value.resize(50);
            object.data.assign(25, element);
        }
#endif

        bio::stream<bio::back_insert_device<BinaryData>> os { serialized_data };
        boost::archive::binary_oarchive oa(os, flags);

        oa << object;
    }

    std::cout << "Size: " << serialized_data.size() << "\n";

    {
        bio::array_source as { serialized_data.data(), serialized_data.size() };
        bio::stream<bio::array_source> os { as };
        boost::archive::binary_iarchive ia(os, flags);

        B object;
        ia >> object;
    }
}

Printing

Using C style arrays implementation: Size: 20472
Using std::vector implementation: Size: 5256
Using static_vector implementation: Size: 5039

最后的想法

也可以看看:

  • 提高序列化按位序列化能力 https://stackoverflow.com/questions/28121545/boost-serialization-bitwise-serializability
  • https://www.boost.org/doc/libs/1_72_0/libs/serialization/doc/wrappers.html#binaryobjects https://www.boost.org/doc/libs/1_72_0/libs/serialization/doc/wrappers.html#binaryobjects

1(但请记住可移植性,因为您可能已经了解 POD 方法,请参阅C++ Boost::serialization:如何在一个程序中归档对象并在另一个程序中恢复它? https://stackoverflow.com/questions/27073936/c-boostserialization-how-do-i-archive-an-object-in-one-program-and-restore/27075717#27075717)

² 不是 POD,就像 NSMI 一样,您的类型不是 POD

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用带有嵌套结构和最少代码更改的 boost::serialization ? 的相关文章

随机推荐

  • Groupby 过滤器,基于连续序列排序以及 ID 和日期列

    我有一个数据框 如下所示 ID Status Date 0 1 F 2017 06 22 1 1 M 2017 07 22 2 1 P 2017 10 22 3 1 F 2018 06 22 4 1 P 2018 08 22 5 1 F 2
  • jar 名称中的版本

    当我将 maven 项目导入 Intellij 时 它生成的 jar 文件不包含版本 但是maven生成的jar有name version jar格式 所以我最终得到了两个 jar 文件 一个有版本 另一个没有版本 我当然可以在 Intel
  • Javascript:关闭字符串中打开的 HTML 标签

    我有一个包含 HTML 代码的 JavaScript 字符串 我显示它 并根据字数附加了一个阅读更多 更少切换器 问题是 当我缩小 HTML 代码时 它可能有开放标签 假设 p A computer is a general purpose
  • 使用 MySQL 实现物化视图(汇总表)的首选方法

    我正在工作中开发一个项目 我需要为其创建和维护汇总表出于性能原因 我相信正确的术语是物化视图 我这样做有两个主要原因 非规范化 我尽可能地规范化表格 因此 在某些情况下 我必须连接许多表才能提取数据 我们使用 MySQL Cluster 它
  • 如何使用swift在表格视图中实现图像的延迟加载

    我想使用 swift 对我的表视图使用延迟加载概念 在我的表格视图中 我显示了多个包含产品图像和产品名称的单元格 请帮助我找到解决方案 旧的解决方案 因为你没有显示任何代码 这是给您的示例 func tableView tableView
  • 如何在运行时创建 celery 队列,以便工作人员拾取发送到该队列的任务?

    我正在使用 django 1 4 celery 3 0 rabbitmq 为了描述该问题 我的系统中有许多内容网络 并且我需要一个队列来处理与每个网络相关的任务 然而 内容是在系统运行时动态创建的 因此我需要动态创建队列并让现有工作人员开始
  • CSS 变量中的 CSS calc() 行为

    我对使用 calc 设置 CSS 变量的行为感到好奇 Example test halfWidth calc 100 2 现在 如果 test元素 比如说div 宽 500px 我想要 halfWidth变量设置为 250px 但是 据我所
  • 急切地处置 ManualResetEvent

    我有一个类 它允许其他线程等待 直到它使用 a 完成操作ManualResetEventSlim 操作通常很简短 这个类没有明确的生命周期 因此没有一个地方可以轻松关闭该事件 相反 我想在事件完成后立即关闭该事件 一旦收到信号 并且在任何等
  • 在 Android 中滚动 listView 时选定的列表项颜色会移动

    在我的 Android 应用程序中 我使用列表视图 列表视图的代码如下
  • 在Python中将文本输出到多个终端

    我使用Python和ArchLinux 我正在用 Python 编写一个简单的人工智能作为学校项目 因为这是一个学校项目 并且我想清楚地演示它在做什么 所以我的目的是有一个不同的终端窗口来显示每个子进程的打印输出 一个终端显示句子如何被解析
  • 将画布设置为背景 - Javascript [重复]

    这个问题在这里已经有答案了 我试图弄清楚如何将我创建的画布转换为 HTML 正文的背景图像 谢谢
  • 如何使用样条线绘制 Cox 风险模型

    我有以下模型 coxph Surv fulength mortality 1 pspline predictor 其中 fulength 是随访时间 包括死亡率 predictor 是死亡率的预测因子 上面命令的输出是这样的 coef se
  • R 直方图中的确切箱数

    我在 R 中制作直方图时遇到困难 问题是我告诉它制作 5 个容器 但它制作了 4 个 我告诉它制作 5 个 它制作了 8 个 data lt c 5 28 14 64 37 25 78 9 44 92 8 96 19 22 34 81 33
  • Excel:列出 2 个数字之间的数字

    我想知道是否有人知道列出 2 个值之间的所有数字的公式 例如 如果单元格 F2 中有 12 而 G2 中有 17 我想要一个显示 13 14 15 16 的公式在单元格 H2 中 Thanks 使用 Excel 工作表函数无法完成此操作 为
  • SQL Server 2000 相当于 ON DUPLICATE KEY?

    SQL Server 2000 是否有与 MySQL ON DUPLICATE KEY 子句等效的功能 这个答案 https stackoverflow com questions 1197733 does sql server offer
  • CoreData 获取关系计数和按另一个关系分组的请求 (m2n)

    在我的 CoreData 模型中 我有一个使用中间实体建模的 n2n 关系 Person 1 lt Person2Appointment gt 1 Appointment The Person2Appointment实体看起来像这样 int
  • 如何使用 AJAX 渲染部分内容?拉拉维尔 5.2

    我现在的情况是想列出有关存储在 MYSQL 数据库中的停车位的信息 我正在使用 AJAX 调用 API 端点 api spots 并返回景点列表 我使用刀片语法创建了一个部分视图来布局信息 partials Spot blade php 我
  • EPPlus 阅读列标题

    有没有一种简单的方法可以告诉 EPPlus 一行是标题 或者我应该通过使用 SelectedRange 指定范围来创建标题 将其从工作表中删除并迭代保留的单元格 我最终这样做了 class Program static void Main
  • 在MVC视图层从DATASET中提取数据

    我被告知在 MVC 中使用旧的传统 SQL 方式 因此创建了登录注册页面 但现在的问题是我无法从数据集中将数据返回到 VIEW Model public ConnectionStatus Login db String email Stri
  • 如何使用带有嵌套结构和最少代码更改的 boost::serialization ?

    目前我们使用存储在嵌套结构中的 POD 例子 define MaxNum1 100 define MaxNum2 50 struct A int Value MaxNum1 char SomeChar a struct B A data M