提升序列化:读取不同类型的数据

时间:2015-07-21 19:49:12

标签: c++ class parsing boost boost-serialization

我有一个C ++ / CLI项目,它使用boost序列化来序列化三个不同的类。我想知道是否可以解析boost序列化归档的第一行,以便知道在此归档中序列化了哪个类,然后创建相应类的对象并将归档反序列化为对象。该行将包含一个ID(可能是枚举类的int或值),以标识序列化的类。

1 个答案:

答案 0 :(得分:4)

您选择的存档实施已经处理了文件格式。

在实践中,boost::archive::text_oarchiveboost::archive::binary_oarchiveboost::archive::xml_oarchive

只要您的存档类型本身不变,您就可以非常轻松地使用Boost Variant来区分您的有效负载。换句话说,让序列化框架为您完成工作,而不是围绕它进行“管道编带”:

这是一个演示,可以序列化3个不同的(复合)有效载荷和往返,但实际上没有有效载荷的外部知识:

<强> Live On Coliru

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <boost/serialization/variant.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp>

#include <boost/serialization/access.hpp>

struct A {
    int simple;

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

struct B {
    std::string text;

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

struct C {
    A composed_a;
    B composed_b;

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

struct FileContents { // conventions...
    boost::variant<A, B, C> payload;

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


#include <sstream>
#include <boost/lexical_cast.hpp>

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// For our roundtrip test, implement streaming as well so we can independently check equivalence
inline static std::ostream& operator<<(std::ostream& os, A const& v) {
    return os << "A{" << v.simple << "}";
}
inline static std::ostream& operator<<(std::ostream& os, B const& v) {
    return os << "B{" << v.text << "}";
}
inline static std::ostream& operator<<(std::ostream& os, C const& v) {
    return os << "C{" << v.composed_a << ", " << v.composed_b << "}";
}

void roundtrip_test(FileContents const& original) {
    std::stringstream ss;
    {
        boost::archive::text_oarchive oa(ss);
        oa << original;
    }

    {
        boost::archive::text_iarchive ia(ss);

        FileContents clone;
        ia >> clone;

        std::string const before = boost::lexical_cast<std::string>(original.payload);
        std::string const after  = boost::lexical_cast<std::string>(clone.payload);

        std::cout << "Roundtrip '" << before << "': " << std::boolalpha << (before == after) << "\n";
    }
}

int main() {
    roundtrip_test({ A { 42 } });
    roundtrip_test({ B { "Life The Universe And Everything" } });
    roundtrip_test({ C { {42}, { "Life The Universe And Everything" } } });
}

输出为:

Roundtrip 'A{42}': true
Roundtrip 'B{Life The Universe And Everything}': true
Roundtrip 'C{A{42}, B{Life The Universe And Everything}}': true