2015-07-21 58 views
3

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

回答

2

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

在实践中,这将是boost::archive::text_oarchive,boost::archive::binary_oarchive,boost::archive::xml_oarchive

只要您的存档类型本身不会发生变化,您就可以非常轻松地使用升压变体来区分您的有效载荷。换句话说,使序列化框架为你做的工作,而不是围绕它的“管道录音”:

这里是一个演示序列化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 
+0

太棒了。 FileContents结构就是我错过的。非常感谢你。 – DreamTool

+0

今天早上我试图实现这个解决方案,但我不明白如何正确使用boost :: variant。我创建了一个base_project类,它对数据成员有boost :: variant ,但是当我将一个local_uni_project传递给我的序列化函数(该函数将输入中的base_project对象)时,会出现一个不合适的转换错误。 – DreamTool

+0

我只能猜测你的实际代码。如果这些类型是相关类型(继承关系),则可能存在模糊的转换。 _(同样,在这种情况下,您显然希望通过指向基类的类来注册用于序列化的多态类型。)_。如果不是,你能展示一个[SSCCE](http://sscce.org/)吗? – sehe