Построить объект из архива буст сериализации - PullRequest
1 голос
/ 06 марта 2012

Можно ли строить объекты прямо из архива?

Как то так ...

// Non-working pseudo code
struct Foo {
    BOOST_SERIALIZATION_SPLIT_MEMBER();
    std::vector<int> data;

    Foo() {
        // populate "data" by doing calculation
        data.push_back(1); data.push_back(2);
    }

    template<class Archive>
    Foo( Archive & ar ) {
        // populate "data" by rading the archive
    }

    template<class Archive>
    void save(Archive & ar, const unsigned int version) const {
        // Normal serialization of data
        ar << data;
    }
};

int main(int argc, const char *argv[])
{
    // deserialize
    boost::archive::text_iarchive oar(std::cin);
    Foo foo(oar);

    return 0;
}

Ответы [ 2 ]

1 голос
/ 27 февраля 2016

Вы можете использовать конструктор десериализации :

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

#include <fstream>

class Point
{
public:
    Point() = default;
    Point(boost::archive::text_iarchive& archive)
    {
        archive >> *this;
    }

    float x = 1.;
    float y = 2.;

private:
    friend class boost::serialization::access;

    template<class TArchive>
    void serialize(TArchive & archive, const unsigned int version)
    {
        archive & x;
        archive & y;
    }
};


int main()
{
    Point p;
    p.x = 5;
    p.y = 6;

    std::ofstream outputStream("test.archive");
    boost::archive::text_oarchive outputArchive(outputStream);
    outputArchive << p;
    outputStream.close();

    std::ifstream inputStream("test.archive");
    boost::archive::text_iarchive inputArchive(inputStream);

    Point pointRead(inputArchive);

    std::cout << pointRead.x << " " << pointRead.y << std::endl;

    return 0;
}
0 голосов
/ 30 марта 2016

Как я уже сказал в комментарии.Да, нет проблем с построением из архива.(Другая альтернатива - использовать функцию static load, но это может привести к снижению производительности.)

Единственная потенциальная проблема, которую я вижу в вашем подходе, заключается в том, что ваш конструктор может принимать почти все в качестве аргумента и может создавать проблемы.И это может помешать конструктору копирования и другим конструкторам с одним аргументом, полагающимся на неявное преобразование.

Таким образом, нужно ограничиться только получением архивов.

Существуют различные методы, чтобы сделать это, но основанные нав этом разговоре http://marc.info/?l=boost&m=121131260728308&w=2, и тем фактом, что дерево наследования archives является задокументированным http://www.boost.org/doc/libs/1_35_0/libs/serialization/doc/class_diagram.html, Я думаю, что это лучшее решение - проверить, что аргумент полученот basic_iarchive.

#include<type_traits>
struct Foo {
    ...
    std::vector<int> data;    
    Foo() {
        // populate "data" by doing calculation
        data.push_back(1); data.push_back(2);
    }

    template<class IArchive, 
        typename = std::enable_if_t<std::is_base_of<boost::archive::detail::basic_iarchive, IArchive>::value>>
    Foo( IArchive & ar ) {
        ar >> data;
        // populate "data" by reading the archive
    }
    ...    
};

int main(int argc, const char *argv[])
{
    // deserialize
    boost::archive::text_iarchive iar(std::cin); 
    Foo foo(iar); // will also work with other archives
}

Что касается того, что происходит, когда ваши данные не являются конструктивными по умолчанию, см. обсуждение выше.

...