Opened 11 years ago

Closed 11 years ago

Last modified 10 years ago

#5679 closed Bugs (invalid)

boost::serialization::primitive_type used with polymorphic archive fails to compile

Reported by: boost@… Owned by: Robert Ramey
Milestone: To Be Determined Component: serialization
Version: Boost 1.47.0 Severity: Problem
Keywords: uuid serialization polymorphic Cc:

Description

Not sure if this belongs with uuid or serialization, but the uuid library has a test that passes for non-polymorphic archive types; see ".../libs/uuid/test/test_serialization.cpp".

To trigger the problem, take the (above) test file, include some polymorphic archives, e.g.

#include <boost/archive/polymorphic_binary_oarchive.hpp>
#include <boost/archive/polymorphic_binary_iarchive.hpp>

and extend main():

    test_archive<polymorphic_binary_oarchive, polymorphic_binary_iarchive, ostringstream, istringstream>();

(apologies if this is fixed post-1.44)

Change History (4)

comment:1 by boost@…, 11 years ago

Summary: Serialization of uuid with polymorphic archive fails to compileboost::serialization::primitive_type used with polymorphic archive fails to compile
Version: Boost 1.44.0Boost 1.47.0

A bit of further investigation reveals this to be an issue with using boost::serialization::primitive_type and polymorphic archive types.

UUID just happens to be a case.

Here's a test to demonstrate: (Note: this was tested against 1.47; the problem is still present.)

#include <sstream>

#include <boost/archive/polymorphic_binary_oarchive.hpp>
#include <boost/archive/polymorphic_binary_iarchive.hpp>

struct MyPrimitiveType
{
    int n_;

    template <typename Ar>
    void serialize(Ar &ar, unsigned const)
    {
        ar & BOOST_SERIALIZATION_NVP(n_);
    }

    friend bool operator==(MyPrimitiveType const &l, MyPrimitiveType const &r)
    {
        return l.n_ == r.n_;
    }
};

BOOST_CLASS_IMPLEMENTATION(MyPrimitiveType, boost::serialization::primitive_type)


int main( int /* argc */, char* /* argv */[] )
{
    using namespace boost::archive;

#if 1
    typedef polymorphic_binary_oarchive oarch;
    typedef polymorphic_binary_iarchive iarch;
#else
    typedef binary_oarchive oarch;
    typedef binary_iarchive iarch;
#endif

    std::stringstream stream;

    MyPrimitiveType pt;
    pt.n_ = 99;

    MyPrimitiveType pt2;
    pt2.n_ = 0;

    // save
    {
        oarch oa(stream);

        oa << BOOST_SERIALIZATION_NVP(pt);
    }

    // load
    {
        iarch ia(stream);

        ia >> BOOST_SERIALIZATION_NVP(pt2);
    }

    assert(pt == pt2);
}

comment:2 by Robert Ramey, 11 years ago

Resolution: invalid
Status: newclosed

I don't think it is possible to fix this.

Here is the short explanation of the polymorphic archive concept.

a) One compiles his serialization implementations against the polymorphic_oarchive class. This means that your classes will be saved to any kind of output archive with out instantiating any new code. This applies for all future and past output archive classes.

b) marking a type as "primitive" indicates that the code for doing the serialization is to be found in the set of functions which are compiled in the .._oprimitive.hpp file.

c) If one would add now "primitive" types to a polymorphic archive - this would totally defeat the original goal of the polymorphic archive.

In a nutshell - instantiating code for your own class at the ..._oprimitive level is incompatiable with the polymorphic oarchive idea that we can use the already made archives without doing any new instantiation.

I realize that this is not at all clear in the explanation of the polymorphic archives. When I first looked at your code I thought it was a bug. It was only after an hour (or more!) of experimentation that I came to this understanding.

Thanks for taking the time to prepare your test case. I'll put a little bit of the explanation in the documentation.

Robert Ramey

comment:3 by boost@…, 11 years ago

Well, okay, that seems fair enough. However, where does that leave boost::uuid? - it was the serialization of this type that originally tripped me up.

Was it incorrect for uuid to have used boost::serialization::primitive_type? Should this issue be transferred to that library?

As it stands, uuid can not be serialized to a polymorphic archive.

comment:4 by rodolfo@…, 10 years ago

Hi, I'm using boost-1_49 and got stuck by this "bug". One solution, at least for streamable types, might be a template overload of polymorphic_oarchive_impl::save that converts the value to a string, then dispatches it to save(const std::string *).

How about it?

Note: See TracTickets for help on using tickets.