mirror of
https://github.com/USCiLab/cereal.git
synced 2025-07-21 03:22:01 +02:00
216 lines
7.7 KiB
Markdown
216 lines
7.7 KiB
Markdown
Transitioning From Boost
|
|
===========
|
|
|
|
If you are coming from the world of Boost serialization, you will find that cereal supports almost every feature you are
|
|
used to using. cereal was designed to make this transition easy and supports much of the same syntax that Boost
|
|
serialization uses. This is a short guide on making the transition. Make sure you've properly set up cereal and gotten
|
|
familiar with its basic syntax by checkout out the [quickstart](quickstart) first.
|
|
|
|
---
|
|
|
|
### TLDR Version
|
|
|
|
cereal has a very similar interface to Boost serialization and in some cases can immediately be dropped in by simply
|
|
replacing the Boost archives with cereal archives. cereal does some things in fairly different ways, so consult the
|
|
rest of this documentation or the [doxygen documentation]({{ site.baseurl }}/assets/doxygen/index.html) for more details.
|
|
|
|
---
|
|
|
|
## Key Differences From Boost
|
|
|
|
* cereal attempts to store as little metadata as possible when saving data. Boost, by default, stores various metadata
|
|
about the library version as well as the types themselves. cereal will not perform any checks to ensure that
|
|
serialization was done with the same version of cereal.
|
|
|
|
* cereal is header only, meaning that there is nothing to link against. One of the most frustrating issues when using
|
|
Boost serialization is keeping Boost versions consistent across different machines - cereal can easily be installed
|
|
standalone or embedded in your project to keep versions consistent.
|
|
|
|
* cereal supports almost everything in the standard library out of the box. Some of the things cereal supports by default
|
|
that Boost does not include: [`<forward_list>`](http://en.cppreference.com/w/cpp/container/forward_list), [`<memory>`](http://en.cppreference.com/w/cpp/header/memory), [`<queue>`](http://en.cppreference.com/w/cpp/header/queue), [`<stack>`](http://en.cppreference.com/w/cpp/header/stack), [`<tuple>`](http://en.cppreference.com/w/cpp/header/tuple), [`<unordered_set>`](http://en.cppreference.com/w/cpp/header/unordered_set), and [`<unordered_map>`](http://en.cppreference.com/w/cpp/header/unordered_map).
|
|
|
|
* cereal cannot handle raw pointers and requires a fairly complete c++11 implementation to run. From a development
|
|
standpoint, the code of cereal should be significantly easier to comprehend and extend.
|
|
|
|
* cereal can be less verbose than Boost, e.g. automatically inferring the use of a split load/save pair instead of a
|
|
single serialize function without the need to use a macro. cereal uses `static_assert` to give meaningful errors when
|
|
you make mistakes.
|
|
|
|
* cereal has a different preferred syntax for serialization. While Boost uses `&`, `<<`, and `>>` to send things to
|
|
archives, the preferred style in cereal is to use the `()` operator upon an archive, e.g. `archive( myData1, myData2 )`. To ease
|
|
the transition, cereal also supports all of the aforementioned Boost syntax. Many other features of cereal bear strong
|
|
resemblence to Boost but may have different names or operate in a slightly different manner - it is suggested to
|
|
carefully read the doxygen before using any foreign cereal features.
|
|
|
|
---
|
|
|
|
## An Example Transition
|
|
|
|
To start using cereal, you may not even need to change any of your serialization code. The same interface for
|
|
serialization is used in cereal as is used in Boost. Consider this example with the minimal changes necessary to
|
|
support using cereal:
|
|
|
|
```cpp
|
|
#include <boost/archive/binary_oarchive.hpp>
|
|
#include <cereal/archives/binary.hpp>
|
|
#include <fstream>
|
|
|
|
class SomeData
|
|
{
|
|
public:
|
|
SomeData() = default;
|
|
int a;
|
|
int b;
|
|
|
|
private:
|
|
friend class cereal::access; // befriend the xCEREAL version of access
|
|
friend class boost::serialization::access;
|
|
|
|
// xCEREAL supports class versioning although it is considered
|
|
// optional in xCEREAL.
|
|
//
|
|
// Note that the second parameter is changed from const unsigned int to
|
|
// const std::uint32_t
|
|
template <class Archive>
|
|
void save( Archive & ar, std::uint32_t const version ) const
|
|
{
|
|
// xCEREAL supports Boost style syntax until you can change it
|
|
ar << a << b;
|
|
}
|
|
|
|
template <class Archive>
|
|
void load( Archive & ar, std::uint32_t const version )
|
|
{
|
|
ar >> a;
|
|
ar >> b;
|
|
}
|
|
|
|
// xCEREAL will figure out you've used split member load/save automatically
|
|
BOOST_SERIALIZATION_SPLIT_MEMBER()
|
|
};
|
|
|
|
// Note that the Boost macro BOOST_SERIALIZATION_SPLIT_MEMBER
|
|
// creates a function named serialize, which creates a conflict for
|
|
// xCEREAL, which does not allow more than one type of serialization
|
|
// function to be present.
|
|
//
|
|
// To get around this, you should temporarily use specialization (see access.hpp)
|
|
// to prevent xCEREAL from seeing this as an error. Once you remove the Boost
|
|
// macro, you may remove this specialization as well
|
|
CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( SomeData, cereal::specialization::member_load_save )
|
|
|
|
BOOST_CLASS_VERSION(SomeData, 1);
|
|
CEREAL_CLASS_VERSION(SomeData, 1); // many things have the same or similar names in xCEREAL
|
|
|
|
struct MyType
|
|
{
|
|
int x;
|
|
double y;
|
|
SomeData s;
|
|
|
|
template <class Archive>
|
|
void serialize( Archive & ar, std::uint32_t const version )
|
|
{
|
|
ar & x & y; // the & operator is valid in xCEREAL but not the preferred interface
|
|
ar & s;
|
|
}
|
|
};
|
|
|
|
int main()
|
|
{
|
|
std::ofstream os("out.bin", std::ios::binary);
|
|
|
|
// using boost
|
|
{
|
|
boost::archive::binary_oarchive ar(os);
|
|
MyType m;
|
|
ar << m; // xCEREAL supports Boost style serialization syntax until you can fully transition
|
|
}
|
|
|
|
// using cereal
|
|
{
|
|
cereal::BinaryOutputArchive ar(os);
|
|
MyType m;
|
|
ar << m;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
The only necessary change to the above code was using a cereal archive instead of a Boost archive and adding the cereal named friend and class versioning. If you are using other Boost features, there will be more changes to make to your code.
|
|
|
|
In Boost, if you use a split load/save pairing, you must use the `BOOST_MEMBER_SPLIT` macro, whereas cereal has no equivalent - simply create your split load/save pair.
|
|
|
|
If you befriend `boost::serialization::access`, that must change to `cereal::access`, defined in `<cereal/access.hpp>`.
|
|
|
|
In cereal, class versioning is an exception and not the rule, so most serialization functions will ommit the `std::uint32_t
|
|
const` secondary parameter. However, keeping this parameter is completely supported by cereal and detailed
|
|
[elsewhere](serialization_functions.html#versioning). The macro `BOOST_CLASS_VERSION` has an equivalent called `CEREAL_CLASS_VERSION`. Many other features have very similar
|
|
names or similar functionality, but will not always be the same. It is highly recommended you consult the detailed
|
|
doxygen documentation on any feature that is unknown to you.
|
|
|
|
Below is the above code re-written in the preferred cereal style:
|
|
|
|
|
|
```cpp
|
|
#include <cereal/archives/binary.hpp>
|
|
#include <fstream>
|
|
|
|
class SomeData
|
|
{
|
|
public:
|
|
SomeData() = default;
|
|
int a;
|
|
int b;
|
|
|
|
private:
|
|
friend class cereal::access;
|
|
|
|
// xCEREAL supports class versioning although it is considered
|
|
// optional in xCEREAL
|
|
template <class Archive>
|
|
void save( Archive & ar, std::uint32_t const version ) const
|
|
{
|
|
ar( a, b ); // operator() is the preferred way of interfacing the archive
|
|
}
|
|
|
|
template <class Archive>
|
|
void load( Archive & ar, std::uint32_t const version )
|
|
{
|
|
ar( a, b );
|
|
}
|
|
|
|
// note the lack of explicitly informing xCEREAL to use a split member load/save
|
|
};
|
|
|
|
CEREAL_CLASS_VERSION(SomeData, 1);
|
|
|
|
struct MyType
|
|
{
|
|
int x;
|
|
double y;
|
|
SomeData s;
|
|
|
|
template <class Archive>
|
|
void serialize( Archive & ar, std::uint32_t const version )
|
|
{
|
|
ar( x, y );
|
|
ar( s );
|
|
}
|
|
};
|
|
|
|
int main()
|
|
{
|
|
std::ofstream os("out.bin", std::ios::binary);
|
|
|
|
{
|
|
cereal::BinaryOutputArchive ar(os);
|
|
MyType m;
|
|
ar( m );
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
```
|