Boost logo

Boost Users :

Subject: [Boost-users] [Serialization] STL Containers and Non-Default Constructors
From: Trevor Thoele (lordimmortal2013_at_[hidden])
Date: 2015-05-20 02:17:19


I have recently changed from a hand-rolled serializer to Boost's and while
it's mostly been fantastic, there's one problem that I can't seem to shake -
I cannot get it to serialize non-default constructible types.
It fails on trying to generate code that requires the usage of a default
constructor.

In non-associative types (list/deque/vector), the loader seems to be calling
the container's resize function with a default value_type argument,
resulting in the attempted creation of the object through the default
constructor.

In associative types, the loader attempts to create a default constructed
value_type, which results in an std::pair being defaultly constructed with
one of the pieces being the non-default constructible type.

The code below fails during compilation with the error "'A' : no appropriate
default constructor available". It was built with MSVC++2013.

#include <list>
#include <fstream>
#include <boost\archive\binary_iarchive.hpp>
#include <boost\archive\binary_oarchive.hpp>
#include <boost\serialization\access.hpp>
#include <boost\serialization\list.hpp>

class A
{
private:
    template<class Archive>
    void serialize(Archive &archive, unsigned int version)
    {
        archive & myInt;
    }
    friend boost::serialization::access;
public:
    int myInt;
    A(int myInt) : myInt(myInt) {}
    A(const A &arg) : myInt(arg.myInt) {}
    A& operator=(const A &arg)
    {
        myInt = arg.myInt;
        return *this;
    }

    bool operator==(const A &arg) const
    {
        return myInt == arg.myInt;
    }
};

namespace boost
{
    namespace serialization
    {
        template<class Archive>
        inline void load_construct_data(Archive &archive, A *a, unsigned int
file_version)
        {
            ::new(a)A(0);
        }
    }
}

int main()
{
    {
        std::ofstream stream("file");
        boost::archive::binary_oarchive archive(stream);

        std::list cont;
        cont.push_back(A(1));
        archive << cont;
    }
    
    {
        std::ifstream stream("file");
        boost::archive::binary_iarchive archive(stream);

        std::list cont;
        archive >> cont;
    }
}

My question is: is this behavior known and what is the best solution to this
for an end-user? The tutorial for STL container serialization mentions using
load/save_construct_data to get around this problem, yet the attempted code
generation above do not take that solution into account so compilation will
fail even if you overload those templates.

The only solutions I can think of to circumvent this problem would be to
require a public (the code ultimately fails in std code, which I guess you
may be able to friend but would be quite strange) default constructor, or to
hand-roll STL container serialization through non-intrusive
serialize/save/load overloads and skip the provided overloads entirely.

--
View this message in context: http://boost.2283326.n4.nabble.com/Serialization-STL-Containers-and-Non-Default-Constructors-tp4675790.html
Sent from the Boost - Users mailing list archive at Nabble.com.

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net