Как сериализовать boost :: dynamic_bitset?

Как сериализовать класс с членом boost :: dynamic_bitset?

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/dynamic_bitset.hpp>
#include <boost/serialization/bitset.hpp>
#include <sstream>

class A
{
friend class boost::serialization::access;
boost::dynamic_bitset<> x;
template<class Archive>
void serialize(Archive & ar, const unsigned int){
ar & x;
}
};

int main()
{
A a;
std::stringstream ss;
boost::archive::text_oarchive oa(ss);
oa << a;
return 0;
}

Компиляция дает ошибку (повышение 1.57)

In file included from /usr/include/boost/serialization/extended_type_info_typeid.hpp:37:0,
from /usr/include/boost/archive/detail/oserializer.hpp:38,
from /usr/include/boost/archive/detail/interface_oarchive.hpp:23,
from /usr/include/boost/archive/detail/common_oarchive.hpp:22,
from /usr/include/boost/archive/basic_text_oarchive.hpp:32,
from /usr/include/boost/archive/text_oarchive.hpp:31,
from dynamic_bitset_setial.cpp:1:
/usr/include/boost/serialization/access.hpp: In static member function ‘static void boost::serialization::access::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::dynamic_bitset<>]’:
/usr/include/boost/serialization/serialization.hpp:69:5:   instantiated from ‘void boost::serialization::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::dynamic_bitset<>]’
/usr/include/boost/serialization/serialization.hpp:128:9:   instantiated from ‘void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::dynamic_bitset<>]’
/usr/include/boost/archive/detail/oserializer.hpp:148:5:   instantiated from ‘void boost::archive::detail::oserializer<Archive, T>::save_object_data(boost::archive::detail::basic_oarchive&, const void*) const [with Archive = boost::archive::text_oarchive, T = boost::dynamic_bitset<>]’
dynamic_bitset_setial.cpp:25:1:   instantiated from here
/usr/include/boost/serialization/access.hpp:118:9: error: ‘class boost::dynamic_bitset<>’ has no member named ‘serialize’

5

Решение

dynamic_bitset<> не сериализуемо, как вы узнали (std::bitset<N> это другой тип).

Не волнуйтесь, вы можете добавить его без особых усилий:

namespace boost { namespace serialization {

template <typename Ar, typename Block, typename Alloc>
void save(Ar& ar, dynamic_bitset<Block, Alloc> const& bs, unsigned) {
size_t num_bits = bs.size();
std::vector<Block> blocks(bs.num_blocks());
to_block_range(bs, blocks.begin());

ar & num_bits & blocks;
}

template <typename Ar, typename Block, typename Alloc>
void load(Ar& ar, dynamic_bitset<Block, Alloc>& bs, unsigned) {
size_t num_bits;
std::vector<Block> blocks;
ar & num_bits & blocks;

bs.resize(num_bits);
from_block_range(blocks.begin(), blocks.end(), bs);
bs.resize(num_bits);
}

template <typename Ar, typename Block, typename Alloc>
void serialize(Ar& ar, dynamic_bitset<Block, Alloc>& bs, unsigned version) {
split_free(ar, bs, version);
}

} }

Это работает, например Жить на Колиру

int main() {
A a;
for (int i=0; i<128; ++i)
a.x.resize(11*i, i%2);

std::stringstream ss;
{
boost::archive::text_oarchive oa(ss);
oa << a;
}
std::cout << ss.str();
{
boost::archive::text_iarchive ia(ss);
A b;
ia >> b;

assert(a.x == b.x);
}
}

Обратите внимание, что если вы не можете позволить себе скопировать вектор блоков, то также легко добавить сериализацию непосредственно в m_bits уровень, но это требует навязчивых изменений (доступ друга требуется как минимум).

Такую вещь можно легко добавить для повышения в запросе на включение.

Обновить добавил, что тянуть запрос

4

Другие решения

Я пошел вперед и подал запрос на получение добавить поддержку сериализации в Boost Dynamic Bitset

Сериализация с использованием открытого интерфейса не является оптимальной, так как to_block_range()/from_block_range() требуют копирования m_bits (и последующие resize()).

Я добавил универсальную реализацию в Boost Dynamic Bitset. Изменения полностью объединяются с разработчиком или мастером (1_58_0).

изменения

Реализация дополнена

  • минимальная навязчивость, только вложенный друг (class serialization_impl;) был переадресован в «замочную скважину» для обязательного доступа друзей через
  • Этот класс, а также фактический хук ADL для ускоренной сериализации реализованы в отдельном заголовке (dynamic_bitset/serialization.hpp, аналогично другим библиотекам boost с поддержкой сериализации).
  • Это означает, что нулевые зависимости от материала Boost Serialization существуют, если только boost/dynamic_bitset/serialization.hpp на самом деле включен
  • Достигнута нулевая копия std::vector<Block>встроенная поддержка в Boost Serialization)

тесты

Второй коммит в запросе на добавление добавляет тесты для этой функции. Я не уверен, как добавить dyn_bitset_unit_tests5.cpp в Jamfile. Я предполагаю, что нужно сделать что-то еще, чтобы обеспечить связь с Boost System и Boost Serialization. Я сам запустил тесты, используя простую оболочку:

#include <modular-boost/libs/dynamic_bitset/dyn_bitset_unit_tests5.cpp>

int main() {
test_main(0, nullptr);
}

Который затем можно скомпилировать и запустить, например, с помощью

g++ main.cpp -lboost_system -lboost_serialization && ./a.out

Отсутствие вывода означает отсутствие ошибок.

5