I've recently learned the pattern of the deserializing constructor (Deserializing constructor doesn't read data correctly) to use serialization with types that do not have default constructors. Now I'm trying to serialize an STL container of these objects, as in the example below:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/vector.hpp>
#include <fstream>
class Point
{
public:
Point(double x) : mX(x) {}
template<class TArchive>
Point(TArchive& archive)
{
archive >> *this;
}
template<class TArchive>
void serialize(TArchive& archive, const unsigned int version)
{
archive & mX;
}
double mX;
};
int main()
{
std::vector<Point> pointVector;
pointVector.push_back(Point(1));
pointVector.push_back(Point(2));
std::ofstream outputStream("test.txt");
boost::archive::text_oarchive outputArchive(outputStream);
outputArchive << pointVector;
outputStream.close();
std::vector<Point> readPointVector;
std::ifstream inputStream("test.txt");
boost::archive::text_iarchive inputArchive(inputStream);
inputArchive >> readPointVector; // Compiler error - no matching function call to Point::Point()
return 0;
}
It seems clear that this shouldn't work, but how would I tell the archive that it needs to use the deserializing constructor to construct the objects that it reads before adding them to the container?
---------- EDIT ----------
After implementing the suggestion in the only answer, this code compiles fine, but doesn't seem to deserialize correctly. The readPointVector
only has size 1 but it should have size 2 (and the data is not correct in the one object that it does contain):
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <fstream>
class Point
{
public:
Point(double x) : mX(x) {}
template<class TArchive>
Point(TArchive& archive)
{
archive >> *this;
}
template<class TArchive>
void serialize(TArchive& archive, const unsigned int version)
{
archive & mX;
}
double mX;
};
template <typename Archive>
Archive& operator >> (Archive& archive, std::vector<Point>& points)
{
points.emplace_back(archive);
return archive;
}
int main()
{
std::vector<Point> pointVector;
pointVector.push_back(Point(5.6));
pointVector.push_back(Point(7.8));
std::cout << pointVector.size() << std::endl; // outputs 2
{
std::ofstream outputStream("test.txt");
boost::archive::text_oarchive outputArchive(outputStream);
outputArchive << pointVector;
outputStream.close();
}
std::vector<Point> readPointVector;
std::ifstream inputStream("test.txt");
boost::archive::text_iarchive inputArchive(inputStream);
inputArchive >> readPointVector;
std::cout << readPointVector.size() << std::endl; // outputs 1 (and readPointVector[0].mX is 2, but should be 7.8)
return 0;
}
You may specialize for vector of Points: