2015-07-21 2 views
3

У меня есть проект C++/CLI, который использует сериализацию boost для сериализации трех разных классов. Я хотел бы знать, можно ли проанализировать первую строку архива последовательной передачи, чтобы узнать, какой класс был сериализован в этом архиве, а затем создать объект соответствующего класса и десериализовать архив в объекте. Эта строка будет содержать идентификатор (возможно, int или значение класса enum), чтобы определить, какой класс был сериализован.Ускорение сериализации: читать данные различного типа

ответ

2

Формат файла уже обрабатывается по вашему выбору реализации архива.

На практике это было бы boost::archive::text_oarchive, boost::archive::binary_oarchive, boost::archive::xml_oarchive.

До тех пор, пока ваш тип архива не изменится, вы можете очень легко использовать вариант Boost для отличия ваших полезных нагрузок. Другими словами, сделайте сериализационную структуру для вас работой, а не «прокладывайте ее» вокруг нее:

Вот демоверсия, которая сериализует 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