Listing1: Serialization of STL containers: a std::vector
example using text archives
Your intuition may tell you to iterate through the STL container in order to serialize it, but it’s actually a lot simpler. First of all, be sure to include the necessary vector.hpp
include file:
#include <boost/serialization/vector.hpp>;
And then simply serialize the std::vector
data member(s):
template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & filenames; }
#include <iostream> #include <vector>; #include <fstream>; #include <boost/serialization/vector.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> class Info { private: // Allow serialization to access non-public data members. friend class boost::serialization::access; // Serialize the std::vector member of Info template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & filenames; } std::vector<std::string> filenames; public: void AddFilename( const std::string& filename ); void Print() const; }; void Info::Print() const { std::copy(filenames.begin(), filenames.end(), std::ostream_iterator<std::string>(std::cout, "\n")); } void Info::AddFilename( const std::string& filename ) { filenames.push_back( filename ); } int main(int argc, char** argv) { Info info; info.AddFilename( "ThisFile.txt" ); info.AddFilename( "ThatFile.txt" ); info.AddFilename( "OtherFile.txt" ); // Save filename data contained in Info object { // Create an output archive std::ofstream ofs( "store.dat" ); boost::archive::text_oarchive ar(ofs); // Save the data ar & info; } // Restore from saved data and print to verify contents Info restored_info; { // Create and input archive std::ifstream ifs( "store.dat" ); boost::archive::text_iarchive ar(ifs); // Load the data ar & restored_info; } restored_info.Print(); return 0; }
Giving you the following output from the restored Info
data:
ThisFile.txt ThatFile.txt OtherFile.txt
Listing 2: Explicitly defining save and load functions
You may need to explicitly define the save and load functions whenever there is asymmetry, such as when versioning is involved. In other words when you don’t want to use the same serialize method to store and restore objects.
The is easily achieved by use of the BOOST_SERIALIZATION_SPLIT_MEMBER()
macro, along with splitting the serialize
method into separate save
and load
methods.
Full code listing as follows, which serializes the same Info
object:
#include <iostream> #include <vector> #include <fstream> #include <boost/serialization/vector.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp>; #include <boost/serialization/split_member.hpp> class Info { private: // Allow serialization to access non-public data members. friend class boost::serialization::access; template<class Archive> void save(Archive & ar, const unsigned int version) const { ar & filenames; } template<class Archive> void load(Archive & ar, const unsigned int version) { ar & filenames; } BOOST_SERIALIZATION_SPLIT_MEMBER() std::vector<std::string> filenames; public: void AddFilename( const std::string& filename ); void Print() const; }; void Info::Print() const { std::copy(filenames.begin(), filenames.end(), std::ostream_iterator<std::string>(std::cout, "\n")); } void Info::AddFilename( const std::string& filename ) { filenames.push_back( filename ); } int main(int argc, char** argv) { Info info; info.AddFilename( "ThisFile.txt" ); info.AddFilename( "ThatFile.txt" ); info.AddFilename( "OtherFile.txt" ); // Save filename data contained in Info object { // Create an output archive std::ofstream ofs( "store.dat" ); boost::archive::text_oarchive ar(ofs); // Save the data ar & info; } // Restore from saved data and print to verify contents Info restored_info; { // Create and input archive std::ifstream ifs( "store.dat" ); boost::archive::text_iarchive ar( ifs ); // Load the data ar & restored_info; } restored_info.Print(); return 0; }
Giving you the following output from the restored Info
data:
ThisFile.txt
ThatFile.txt
OtherFile.txt
Listing 3: Saving and loading multiple objects
The same as listing 2, but what if we wish to save multiple versions of the Info
object. This shows you how:
#include <iostream> #include <vector> #include <fstream> #include <boost/serialization/vector.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/split_member.hpp> class Info { private: // Allow serialization to access non-public data members. friend class boost::serialization::access; template<class Archive> void save(Archive & ar, const unsigned int version) const { ar & filenames; } template<class Archive> void load(Archive & ar, const unsigned int version) { ar & filenames; } BOOST_SERIALIZATION_SPLIT_MEMBER() std::vector<std::string> filenames; public: void AddFilename( const std::string& filename ); void Print() const; }; void Info::Print() const { std::copy(filenames.begin(), filenames.end(), std::ostream_iterator<std::string>(std::cout, "\n")); } void Info::AddFilename( const std::string& filename ) { filenames.push_back( filename ); } int main(int argc, char** argv) { std::vector<Info> infs; Info info1, info2; info1.AddFilename( "ThisFile.txt" ); info2.AddFilename( "ThatFile.txt" ); info2.AddFilename( "OtherFile.txt" ); info2.AddFilename( "ABC" ); info2.AddFilename( "123" ); info2.AddFilename( "XYZ" ); infs.push_back( info1 ); infs.push_back( info2 ); // Save filename data contained in Info object { // Create an output archive std::ofstream ofs( "store.dat" ); boost::archive::text_oarchive ar(ofs); // Save the data ar & infs; } // Restore from saved data and print to verify contents std::vector<Info> restored_info; { // Create and input archive std::ifstream ifs( "store.dat" ); boost::archive::text_iarchive ar( ifs ); // Load the data ar & restored_info; } std::vector<Info>::const_iterator it = restored_info.begin(); for (; it != restored_info.end(); ++it) { Info info = *it; info.Print(); } return 0; }
Giving the following output:
Related post: