Process delete variable from boost serialization

I looked at an example on the Internet about adding a member variable to a serialization function by increasing the version number and adding an “if” around the serialization of this variable.

But what should I do if I delete a member variable? Should I just remove it from the serialization function, and boost will take care of this?

It might get worse if I delete some classes that were “serialized” in the serialization function, do I need to save them only for this serialization code, or is there another way?

+4
source share
1 answer

Background / archive format compatibility

Boost Serialization is pretty easy in a lot of scenarios.

, / , , .

() ( ).

, ++ (, ) , .

std::map<std::string, boost::uuids::uuid>

-

boost::unordered_map<std::string, boost::uuids::uuid>
// or
boost::flat_map<std::string, boost::uuids::uuid>
// or
std::vector<std::pair<std::string, boost::uuids::uuid> >

() , .

, ​​ "" , .

, , " ", " " .

,

1:

: " ".

: serialize - . , . , :

struct MyType {
    MyType();
    MyType(std::string const& v);

  private:
    friend class boost::serialization::access;
    template <typename Ar> void serialize(Ar&, unsigned);

#if DEMO_VERSION == 0

    bool hasValue;
    std::string value;

#elif DEMO_VERSION == 1

    boost::optional<std::string> value;

#endif
};

, .

, - , -:

#if DEMO_VERSION == 0
MyType::MyType()                     : hasValue(false)          {}
MyType::MyType(std::string const &v) : hasValue(true), value(v) {}

template <typename Ar> void MyType::serialize(Ar& ar, unsigned /*file_version*/) {
    ar & hasValue & value; // life was simple in v0
}

#elif DEMO_VERSION == 1
MyType::MyType()                     : value(boost::none)       {}
MyType::MyType(std::string const &v) : value(v)                 {}

template <typename Ar> void MyType::serialize(Ar& ar, unsigned file_version) {
    switch (file_version) {
        case 0: {
            assert(Ar::is_loading::value); // should not be writing old formats
            //
            bool        old_hasValue;      // these fields no longer exist
            std::string oldValue;

            ar & old_hasValue & oldValue;

            // translate to new object semantics/layout
            value.reset();
            if (old_hasValue) value.reset(oldValue);

            break;
        }
        default: // v1+
            ar & value;
    }
}
#endif

Coliru, v0 v0.dat, v1 ( ):

Live On Coliru

BOOST_CLASS_VERSION(MyType, DEMO_VERSION)
#include <fstream>

namespace demo {
    template <typename T> void serialize(std::ostream& os, T const& obj) {
        {
            boost::archive::text_oarchive oa(os);
            oa << obj;
        }
        os.flush();
    }

    template <typename T> void save(std::string const& fname, T const& payload) {
        std::ofstream ofs(fname, std::ios::binary);
        serialize(ofs, payload);
    }

    MyType load(std::string const& fname) {
        std::ifstream ifs(fname, std::ios::binary);

        MyType obj;

        boost::archive::text_iarchive ia(ifs);
        ia >> obj;

        return obj;
    }
}

int main(int, char** cmd) {
    std::cout << "Running " << *cmd << " with DEMO_VERSION=" << DEMO_VERSION << "\n";
    using namespace demo;

#if DEMO_VERSION == 0

    MyType payload("Forty two");
    save     ("v0.dat", payload);  // uses v0 format
    serialize(std::cout, payload); // uses v0 format

#elif DEMO_VERSION == 1

    auto loaded = load("v0.dat");  // still reads the v0 format
    serialize(std::cout, loaded);  // uses v1 format now

#endif
}

for v in 0 1
do
    g++ -std=c++11 -Os -Wall -DDEMO_VERSION=$v main.cpp -o v$v -lboost_system -lboost_serialization
    ./v$v
done
Running ./v0 with DEMO_VERSION=0
22 serialization::archive 11 0 0 1 9 Forty two
Running ./v1 with DEMO_VERSION=1
22 serialization::archive 11 0 1 0 0 1 0 9 Forty two

2: /

, , .

" /" , , , , .

, ( " 1" ) PoorMansOptional<std::string>, boost::optional<std::string>. -.

, . , .

+4

Source: https://habr.com/ru/post/1589253/


All Articles