c++boostboost-dynamic-bitset

How to serialize boost::dynamic_bitset?


How to serialize a class with a boost::dynamic_bitset member?

#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;
}

Compiling gives an error (boost 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’

Solution

  • dynamic_bitset<> is not serializable, as you've found out (std::bitset<N> is different type).

    Not to worry, though, you can add it without too much effort:

    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);
            }
    
    } }
    

    This works e.g. Live On Coliru

    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);
        }
    }
    

    Note that if you can't afford to copy the blocks vector, it's equally easy to add serialization directly on the m_bits level, but that requires intrusive changes (friend access required at a minimum).

    Such a thing would easily be added to boost in a pull request.

    Update added that pull request