To serialize and deserialize objects of a class that doesn't have a default constructor using cereal, you can use the load_and_construct
function. Here's how you can do it:
Step 1: Include the necessary cereal headers:
#include <cereal/access.hpp>
#include <cereal/types/string.hpp>
Step 2: In your Weapon
 class, define a load_and_construct
 function:
class Weapon {
public:
Weapon(const std::string& name, int damage)
: name(name), damage(damage) {}
private:
friend class cereal::access;
std::string name;
int damage;
template <class Archive>
void save(Archive& ar) const {
ar(name, damage);
}
template <class Archive>
static void load_and_construct(
Archive& ar,
cereal::construct<Weapon>& construct
) {
std::string name;
int damage;
ar(name, damage);
construct(name, damage);
}
};
In the load_and_construct
function, you deserialize the necessary data members and then use the construct
object to call the appropriate constructor of the Weapon
 class.
Step 3: Serialize and deserialize the Weapon
 object as usual:
#include <cereal/archives/binary.hpp>
#include <fstream>
#include <memory>
int main() {
// Serialization
auto weapon = std::make_unique<Weapon>(
"Sword", 50);
std::ofstream outputFile("weapon.dat");
cereal::BinaryOutputArchive outputArchive(
outputFile);
outputArchive(weapon);
// Deserialization
std::unique_ptr<Weapon> deserializedWeapon;
std::ifstream inputFile("weapon.dat");
cereal::BinaryInputArchive inputArchive(
inputFile);
inputArchive(deserializedWeapon);
}
By using the load_and_construct
function, cereal will be able to deserialize and reconstruct objects of your Weapon
class even though it doesn't have a default constructor.
Note: Make sure to use smart pointers like std::unique_ptr
or std::shared_ptr
when serializing and deserializing objects that are dynamically allocated to ensure proper memory management.
A complete example is below:
// Suppress compilation warnings
#define _SILENCE_CXX23_ALIGNED_STORAGE_DEPRECATION_WARNING
#include <cereal/archives/binary.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/memory.hpp>
#include <fstream>
#include <iostream>
#include <memory>
class Weapon {
public:
Weapon(const std::string& name, int damage)
: name(name), damage(damage) {}
std::string name;
int damage;
private:
friend class cereal::access;
template <class Archive>
void save(Archive& ar) const {
ar(name, damage);
}
template <class Archive>
static void load_and_construct(Archive& ar,
cereal::construct<Weapon>& construct) {
std::string name;
int damage;
ar(name, damage);
construct(name, damage);
}
};
int main() {
// Serialization
auto weapon = std::make_unique<Weapon>(
"Sword", 50);
{
std::ofstream outputFile("weapon.dat");
cereal::BinaryOutputArchive outputArchive(
outputFile);
outputArchive(weapon);
}
// Deserialization
std::unique_ptr<Weapon> deserializedWeapon;
{
std::ifstream inputFile("weapon.dat");
cereal::BinaryInputArchive inputArchive(
inputFile);
inputArchive(deserializedWeapon);
}
std::cout << "Deserialized Weapon:\n";
std::cout << "Name: "
<< deserializedWeapon->name << "\n";
std::cout << "Damage: "
<< deserializedWeapon->damage << "\n";
}
Deserialized Weapon:
Name: Sword
Damage: 50
Answers to questions are automatically generated and may not have been reviewed.
A detailed and practical tutorial for binary serialization in modern C++ using the cereal
library.