Boost.Serialization
Library
Boost.Serialization
Overview
Boost.Serialization is a comprehensive serialization library that makes it possible to convert objects in a C++ program to a sequence of bytes that can be saved and loaded to restore the objects. It enables the reversible deconstruction of arbitrary C++ data structures to a sequence of bytes, which can be used to reconstitute an equivalent structure in another program context. This can be used to implement object persistence, remote parameter passing, or other serialization-required facilities.
Details
As part of the Boost library collection, Boost.Serialization provides industrial-standard quality and reliability. It offers all the features needed for enterprise applications, including non-intrusive serialization, automatic pointer tracking, comprehensive version management, and support for multiple archive formats.
Key features:
- Multiple Archive Formats: Supports text, binary, and XML archives
- Non-Intrusive Design: Can serialize existing classes without modification
- Automatic Pointer Handling: Automatic tracking of pointers and handling of circular references
- Complete STL Support: Built-in support for all STL containers
- Versioning: Independent version management for each class
- Polymorphism Support: Serialization of derived classes through base class pointers
- Cross-Platform: Works on 32/64-bit, Windows, Linux, Solaris, etc.
- Thread Safety: Concurrent reading/writing of different archive instances is permitted
- Array Optimization: Optimizations for contiguous arrays of homogeneous data
Archive interface:
- All archive class interfaces are identical
- Once serialization is defined for a class, it can be serialized to any archive type
- Easy creation of new archive types
- Rich interface allows presenting serialized data as XML in a useful manner
Pros and Cons
Pros
- Industrial Standard Quality: High quality and reliability as a Boost library
- Comprehensive Features: Complete feature set for enterprise-level requirements
- Maturity: Years of proven stability and extensive documentation
- Non-Intrusive: No need to modify existing classes, including library classes
- Automatic Pointer Handling: Safe serialization of complex data structures
- Excellent Extensibility: Easy to create custom archives and serializers
- Large Community: Abundant information and support
- Standards Influence: Track record of contributing to C++ standardization
Cons
- Learning Curve: Time needed for complete understanding due to rich features
- Compile Time: Increased compile times due to heavy template usage
- Binary Size: Large linked library size
- Performance: May have slower processing speed compared to some lightweight libraries
- Dependencies: Dependency on the entire Boost library (partial use possible)
- Modern C++ Support: Conservative adoption of C++11 and later features
References
Code Examples
Basic Serialization
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
class Person {
private:
friend class boost::serialization::access;
std::string name;
int age;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & name;
ar & age;
}
public:
Person() {}
Person(const std::string& n, int a) : name(n), age(a) {}
void print() const {
std::cout << "Name: " << name << ", Age: " << age << std::endl;
}
};
int main() {
// Save object
{
Person person("John Doe", 30);
std::ofstream ofs("person.txt");
boost::archive::text_oarchive oa(ofs);
oa << person;
}
// Load object
{
Person person;
std::ifstream ifs("person.txt");
boost::archive::text_iarchive ia(ifs);
ia >> person;
person.print();
}
return 0;
}
STL Container Serialization
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/string.hpp>
struct Employee {
std::string name;
std::string department;
double salary;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & name & department & salary;
}
};
class Company {
private:
friend class boost::serialization::access;
std::string company_name;
std::vector<Employee> employees;
std::map<std::string, int> department_count;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & company_name;
ar & employees;
ar & department_count;
}
public:
Company() {}
Company(const std::string& name) : company_name(name) {}
void addEmployee(const Employee& emp) {
employees.push_back(emp);
department_count[emp.department]++;
}
};
int main() {
Company company("Tech Corp");
company.addEmployee({"Alice", "Development", 75000});
company.addEmployee({"Bob", "Sales", 65000});
company.addEmployee({"Charlie", "Development", 80000});
// Save with binary archive
{
std::ofstream ofs("company.dat", std::ios::binary);
boost::archive::binary_oarchive oa(ofs);
oa << company;
}
// Load
Company loaded_company;
{
std::ifstream ifs("company.dat", std::ios::binary);
boost::archive::binary_iarchive ia(ifs);
ia >> loaded_company;
}
return 0;
}
Pointers and Polymorphism
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/vector.hpp>
class Shape {
public:
virtual ~Shape() = default;
virtual double area() const = 0;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
// Base class processing
}
};
class Circle : public Shape {
private:
friend class boost::serialization::access;
double radius;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & boost::serialization::base_object<Shape>(*this);
ar & BOOST_SERIALIZATION_NVP(radius);
}
public:
Circle() : radius(0) {}
Circle(double r) : radius(r) {}
double area() const override {
return 3.14159 * radius * radius;
}
};
class Rectangle : public Shape {
private:
friend class boost::serialization::access;
double width, height;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & boost::serialization::base_object<Shape>(*this);
ar & BOOST_SERIALIZATION_NVP(width);
ar & BOOST_SERIALIZATION_NVP(height);
}
public:
Rectangle() : width(0), height(0) {}
Rectangle(double w, double h) : width(w), height(h) {}
double area() const override {
return width * height;
}
};
// Register derived classes
BOOST_CLASS_EXPORT(Circle)
BOOST_CLASS_EXPORT(Rectangle)
int main() {
std::vector<std::shared_ptr<Shape>> shapes;
shapes.push_back(std::make_shared<Circle>(5.0));
shapes.push_back(std::make_shared<Rectangle>(4.0, 6.0));
// Save with XML archive
{
std::ofstream ofs("shapes.xml");
boost::archive::xml_oarchive oa(ofs);
oa << BOOST_SERIALIZATION_NVP(shapes);
}
// Load
std::vector<std::shared_ptr<Shape>> loaded_shapes;
{
std::ifstream ifs("shapes.xml");
boost::archive::xml_iarchive ia(ifs);
ia >> BOOST_SERIALIZATION_NVP(loaded_shapes);
}
for (const auto& shape : loaded_shapes) {
std::cout << "Area: " << shape->area() << std::endl;
}
return 0;
}
Versioning
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/version.hpp>
class Document {
private:
friend class boost::serialization::access;
std::string title;
std::string content;
std::string author; // Added in version 1
int revision_count; // Added in version 2
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & title;
ar & content;
if (version >= 1) {
ar & author;
}
if (version >= 2) {
ar & revision_count;
}
}
public:
Document() : revision_count(0) {}
Document(const std::string& t, const std::string& c)
: title(t), content(c), author("Unknown"), revision_count(1) {}
};
// Specify class version
BOOST_CLASS_VERSION(Document, 2)
int main() {
Document doc("Technical Document", "About Boost.Serialization usage...");
// Save
{
std::ofstream ofs("document.txt");
boost::archive::text_oarchive oa(ofs);
oa << doc;
}
// Can load files from different versions
Document loaded_doc;
{
std::ifstream ifs("document.txt");
boost::archive::text_iarchive ia(ifs);
ia >> loaded_doc;
}
return 0;
}
Non-Intrusive Serialization
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/split_free.hpp>
// Third-party class (cannot be modified)
class ThirdPartyClass {
int private_data;
public:
ThirdPartyClass() : private_data(0) {}
ThirdPartyClass(int data) : private_data(data) {}
int getData() const { return private_data; }
void setData(int data) { private_data = data; }
};
// Non-intrusive serialization functions
namespace boost {
namespace serialization {
template<class Archive>
void save(Archive & ar, const ThirdPartyClass & obj, const unsigned int version) {
int data = obj.getData();
ar & data;
}
template<class Archive>
void load(Archive & ar, ThirdPartyClass & obj, const unsigned int version) {
int data;
ar & data;
obj.setData(data);
}
}
}
// Specify save/load split
BOOST_SERIALIZATION_SPLIT_FREE(ThirdPartyClass)
int main() {
ThirdPartyClass obj(42);
// Save
{
std::ofstream ofs("thirdparty.txt");
boost::archive::text_oarchive oa(ofs);
oa << obj;
}
// Load
ThirdPartyClass loaded_obj;
{
std::ifstream ifs("thirdparty.txt");
boost::archive::text_iarchive ia(ifs);
ia >> loaded_obj;
}
std::cout << "Loaded data: " << loaded_obj.getData() << std::endl;
return 0;
}
Using Custom Archives
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <sstream>
struct Configuration {
std::string app_name;
int version;
std::vector<std::string> modules;
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & app_name & version & modules;
}
};
// Stream-based serialization
std::string serializeToString(const Configuration& config) {
std::ostringstream oss;
boost::archive::text_oarchive oa(oss);
oa << config;
return oss.str();
}
Configuration deserializeFromString(const std::string& data) {
std::istringstream iss(data);
boost::archive::text_iarchive ia(iss);
Configuration config;
ia >> config;
return config;
}
int main() {
Configuration config{"MyApp", 1, {"Core", "UI", "Network"}};
// Serialize to string (can be used for network transmission)
std::string serialized = serializeToString(config);
std::cout << "Serialized: " << serialized << std::endl;
// Deserialize from string
Configuration restored = deserializeFromString(serialized);
return 0;
}