Boost - 仅在大小匹配时反序列化数组
Boost - deserialize an array only when sizes match
当我尝试反序列化的数组大小与最初序列化数组的大小不匹配时,我希望反序列化失败。
到目前为止它只在 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
}
我考虑过:
通过 std::vector
序列化并自己处理,但这可能会导致性能损失
之后检查 arr2
(如果它没有在 arr1_size > arr2_size
上抛出)尾随默认构造的 class 类型元素或其他特殊值)以处理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
,这将是最简单的。如果您需要 header 文件(例如序列化普通数组),仍然有可能 - 避免匹配 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
}
这使用与 built-in 序列化相同的数组序列化机制,因此它应该具有完全相同的性能。如果您能够删除 boost/serialization/array.hpp
,则可以将 MyArrayElementType
更改为模板参数。
当我尝试反序列化的数组大小与最初序列化数组的大小不匹配时,我希望反序列化失败。
到目前为止它只在 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
}
我考虑过:
通过
std::vector
序列化并自己处理,但这可能会导致性能损失之后检查
arr2
(如果它没有在arr1_size > arr2_size
上抛出)尾随默认构造的 class 类型元素或其他特殊值)以处理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
,这将是最简单的。如果您需要 header 文件(例如序列化普通数组),仍然有可能 - 避免匹配 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
}
这使用与 built-in 序列化相同的数组序列化机制,因此它应该具有完全相同的性能。如果您能够删除 boost/serialization/array.hpp
,则可以将 MyArrayElementType
更改为模板参数。