Deserializing STL container of type with no default constructor

落爺英雄遲暮 提交于 2020-01-17 05:13:25

问题


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;
}

回答1:


You may specialize for vector of Points:

template <typename Archive>
Archive& operator >> (Archive& archive, std::vector<Point>& points)
{
    points.emplace_back(archive);
    return archive;
}


来源:https://stackoverflow.com/questions/35732363/deserializing-stl-container-of-type-with-no-default-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!