c++ - Boost - 仅当大小匹配时反序列化数组

标签 c++ serialization boost deserialization stdarray

当我尝试反序列化的数组的大小与原始序列化数组的大小不匹配时,我希望反序列化失败。

到目前为止,仅当 arr1_size > arr2_size 时才会失败我希望它是 arr1_size != arr2_size :

#include <iostream>
#include <sstream>
#include <array>

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/array.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

int main()
{
    const size_t arr1_size = 4, arr2_size = 3;
    std::stringstream ss;

    // save
    std::array<int, arr1_size> arr1;
    boost::archive::text_oarchive oar(ss, boost::archive::no_header);
    oar & arr1;

    // load
    std::array<int, arr2_size> arr2;
    boost::archive::text_iarchive iar(ss, boost::archive::no_header);
    iar & arr2; // throw on size inequality, please
}

Live on Coliru


我想到了:

  • 通过 std::vector 进行序列化并自己处理这个问题,但这可能会导致性能损失

  • 检查arr2之后(如果它没有抛出 arr1_size > arr2_size )对于尾随默认构造的类类型元素或其他特殊值)来处理 arr1_size < arr2_size

有没有什么更简单的东西,最好是由 boost 提供的,但我错过了?

最佳答案

Here是你想要绕过的Boost代码,具体来说这个测试是不够的:

    if(static_cast<std::size_t>(count) > current_count)
        boost::serialization::throw_exception(
            archive::archive_exception(
                boost::archive::archive_exception::array_size_too_short
            )
        );

一种解决方法是用您自己的序列化替换 std::array。如果您可以避免为序列化 std::array 的任何翻译单元包含 header boost/serialization/array.hpp,那么这是最简单的。如果您需要该头文件(例如序列化普通数组),这仍然是可能的 - 避免匹配 Boost templated function 的技巧:

template <class Archive, class T, std::size_t N>
void serialize(Archive& ar, std::array<T,N>& a, const unsigned int /* version */)
...

实现此目的的一种方法是显式指定元素类型:

typedef int MyArrayElementType;

namespace std {
   template<class Archive, size_t N>
   void serialize(Archive& ar, std::array<MyArrayElementType, N>& a, const unsigned int version)
   ...

以下是您的 MCVE 的改编版:

#include <iostream>
#include <sstream>
#include <array>

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/array.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

// Supply your element type here.
typedef int MyArrayElementType;

namespace std {
   template<class Archive, size_t N>
   void serialize(Archive& ar, std::array<MyArrayElementType, N>& a, const unsigned int version) {
      boost::serialization::split_free(ar, a, version);
   }

   template<class Archive, size_t N>
   void save(Archive& ar, const std::array<MyArrayElementType, N>& a, const unsigned int version) {
      // Adapted code from oserializer.hpp save_array_type::invoke().
      boost::serialization::collection_size_type count(N);
      ar << BOOST_SERIALIZATION_NVP(count);
      ar << boost::serialization::make_array(static_cast<MyArrayElementType const*>(&a[0]), count);
   }

   template<class Archive, size_t N>
   void load(Archive& ar, std::array<MyArrayElementType, N>& a, const unsigned int version) {
      // Adapted code from iserializer.hpp load_array_type::invoke().
      boost::serialization::collection_size_type count;
      ar >> BOOST_SERIALIZATION_NVP(count);
      if(static_cast<std::size_t>(count) != N)
         boost::serialization::throw_exception(
            std::runtime_error("std::array size mismatch")
            );
      ar >> boost::serialization::make_array(static_cast<MyArrayElementType*>(&a[0]), count);
   }
}

int main()
{
    const size_t arr1_size = 3, arr2_size = 4;
    std::stringstream ss;

    // save
    std::array<int, arr1_size> arr1;
    boost::archive::text_oarchive oar(ss, boost::archive::no_header);
    oar & arr1;

    // load
    std::array<int, arr2_size> arr2;
    boost::archive::text_iarchive iar(ss, boost::archive::no_header);
    iar & arr2; // throw on size inequality, please
}

Live on CoLiRu

这使用与内置序列化相同的数组序列化机制,因此它应该具有完全相同的性能。如果您能够删除 boost/serialization/array.hpp,您可以将 MyArrayElementType 更改为模板参数。

关于c++ - Boost - 仅当大小匹配时反序列化数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37911894/

相关文章:

python - 如果我有足够的 RAM,如何加快解开大型对象的速度?

java - XMLEncoder 和 XStream 的相对优势是什么?

c++ - 使用 boost 绑定(bind)到仅采用一个参数的方法来 boost 自定义格式化程序

c++ - 如何在 C++ 中将文件保存到桌面?

c++ - C++ 中的高效线程安全单例

c++ - 在使用正则表达式执行函数时逐行解析 inFile

c++ - 试图让我的游戏在 VC 2010 中运行,似乎无法链接 SOIL 库,不知道如何链接,包括游戏源代码

mysql - Wordpress 使用自定义查询搜索序列化元数据

c++ - 使用 boost 图进行图像分割

c++ - boost.graph 1.56.0 和 g++ 4.6.4 编译错误