Boost class serialization, change in member types

后端 未结 1 2013
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-16 12:08

How does one handle switching the type of serialized members while retaining compatability with previous archive? E.g. I want to change float/int to doub

1条回答
  •  隐瞒了意图╮
    2021-01-16 12:54

    You can use the version parameter to version. The documentation gives this example: http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/tutorial.html#versioning

    Note how the version during serialization is specified by the BOOST_CLASS_VERSION macro.

    Here's a proof of concept using the following versions of your data struct: See it Live On Coliru

    struct DataV0
    {
        float f = 3.14;
        int   i = 42;
    
        template
        void serialize(Archive & ar, const unsigned int version)
        {
            if (0 != version) 
                throw std::runtime_error("Unsupported version");
    
            ar & f;
            ar & i;
        }
    };
    

    Now, in your V1 serialization format, you have changed the types as in your question:

    struct DataV1
    {
        double d  = 3.14;
        size_t ul = 42;
    
        template
        void serialize(Archive & ar, const unsigned int version)
        {
            switch(version)
            {
                case 0:
                    { 
                        DataV0 old;
                        ar & old.f;
                        ar & old.i;
    
                        d = old.f;
                        assert(old.i >= std::numeric_limits::min());
                        assert(old.i <= std::numeric_limits::max());
                        ul = static_cast(old.i);
                    }
                    break;
                case 1:
                    ar & d;
                    ar & ul;
                    break;
            }
        }
    };
    
    BOOST_CLASS_VERSION(DataV1, 1)
    

    A full test program:

    template 
    std::string to_string(Data d)
    {
        std::ostringstream oss;
        boost::archive::text_oarchive oa(oss);
    
        oa << d;
    
        return oss.str();
    }
    
    template 
    bool verify(std::string const& text)
    {
        std::istringstream iss(text);
        boost::archive::text_iarchive ia(iss);
    
        Data d;
        ia >> d;
    
        return text == to_string(d);
    }
    
    int main()
    {
        std::string v0text = to_string(DataV0());
        std::string v1text = to_string(DataV1());
    
        std::cout << v0text << '\n';
        std::cout << v1text << '\n';
    
        std::cout << "v0 as v0: " << std::boolalpha << verify(v0text) << "\n";
        std::cout << "v0 as v1: " << std::boolalpha << verify(v0text) << "\n";
    
        std::cout << "v1 as v1: " << std::boolalpha << verify(v1text) << "\n";
        try {
            std::cout << "v1 as v0: " << std::boolalpha << verify(v1text) << "\n";
        } catch (std::exception const& e)
        {
            std::cerr << "Threw the expected '" << e.what() << "'\n";
        }
    
    }
    

    Prints:

    22 serialization::archive 10 0 0 3.1400001 42
    22 serialization::archive 10 0 1 3.1400000000000001 42
    v0 as v0: true
    v0 as v1: false
    v1 as v1: true
    v1 as v0: Threw the expected 'Unsupported version'
    

    0 讨论(0)
提交回复
热议问题