如何将boost::shared_array转换为zfp::array1d解决zfp解压报错
问题背景
需要使用zfp完成数据数组解压操作,根据官方文档说明可使用zfp::array1d类型实现解压,但当前输入数据为boost::shared_array<char>类型。
尝试使用如下代码进行数据转换时无法正常运行:
zfp::array1d raw_data{std::begin(raw_msgpack.data), std::end(raw_msgpack.data)};
抛出如下编译错误:
/usr/include/c++/8/initializer_list:89:5: note: template argument deduction/substitution failed: MsgpackDeserializer.cpp:39:53: note: ‘boost::shared_array<char>’ is not derived from ‘std::initializer_list<_Tp>’ zfp::array1d raw_data{std::begin(raw_msgpack.data), std::end(raw_msgpack.data)};
报错原因
zfp::array1d没有提供双迭代器入参的构造函数,使用花括号传两个迭代器初始化时,编译器会优先匹配std::initializer_list类型的构造重载,因此抛出类型不匹配的编译错误。
另外boost::shared_array<char>本身不存储数组长度信息,也没有实现标准迭代器接口,直接对其调用std::begin/std::end得到的尾后指针是无效值,就算编译通过也会引发内存访问错误。
解决步骤
- 提前从msgpack的元信息中获取待解压数组的实际元素个数,
boost::shared_array本身不记录持有内存的长度,该值必须单独存储/解析。 - 调用
boost::shared_array的.get()方法获取底层连续内存的原始指针,不要使用std::begin/std::end访问其内存。 - 按照zfp的接口规范构造
array1d对象,根据输入数据类型选择对应的数据拷贝或解压逻辑,参考实现如下:
// 替换为你从msgpack中解析到的实际数组元素个数 const size_t array_elem_count = /* 从元数据获取的长度值 */; // 替换为你实际使用的zfp压缩配置,比如压缩率、数据类型等 const double zfp_compress_rate = /* 你的压缩率配置 */; // 构造指定长度的1维zfp数组 zfp::array1d zfp_arr(array_elem_count, zfp_compress_rate); // 场景1:如果shared_array中存储的是未压缩的原始数组数据,直接拷贝内存即可 std::memcpy(zfp_arr.data(), raw_msgpack.data.get(), array_elem_count * sizeof(/* 你的数组元素类型,比如float/double/int */)); // 场景2:如果shared_array中存储的是zfp压缩后的二进制流,调用zfp解压接口完成解析 /* zfp_stream* decompress_stream = zfp_stream_open(nullptr); zfp_stream_set_rate(decompress_stream, zfp_compress_rate, zfp_arr.type(), 1, zfp_false); bitstream* bs = stream_open(raw_msgpack.data.get(), compressed_stream_length); zfp_arr.decompress(decompress_stream); zfp_stream_close(decompress_stream); stream_close(bs); */
注意:如果存储的是zfp压缩流,传入stream_open的内存长度为压缩后二进制流的实际长度,不要传原始未压缩数组的长度,否则会出现解压失败、内存越界问题。
内容的提问来源于stack exchange,提问作者Jieke Wei
相关产品推荐
相关产品推荐

