Build an object from a sequential build archive

Is it possible to create objects directly from the archive?

Something like that...

// 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; } 
+1
source share
2 answers

You can use the descriptor constructor :

 #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; px = 5; py = 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; } 
+1
source

As I said in a comment. Yes, there are no problems with building from the archive. (Another alternative is the static load function, but this can lead to performance penalties).

The only potential problem that I see with your approach is that your constructor can take almost anything as an argument and can cause problems. And this can interfere with the copy constructor and other single argument constructors that rely on implicit conversion.

Thus, you need to limit yourself to archiving.

There are different methods for this, but based on this talk http://marc.info/?l=boost&m=121131260728308&w=2 and the fact that the archives inheritance tree is documented http://www.boost.org/doc/libs /1_35_0/libs/serialization/doc/class_diagram.html , I think that the best solution is to check that the argument is derived from 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 } 

As for what happens when your data is not constructive by default, see the discussion above.

0
source

Source: https://habr.com/ru/post/910078/


All Articles