http://www.boost.org/doc/libs/1_53_0/libs/serialization/example/demo.cpp does not work properly when using polymorphic xml archive
Hi all, I used http://www.boost.org/doc/libs/1_53_0/libs/serialization/example/demo.cpp file as a first introduction to boost serialization. I would like to use polymorphic archives with XML serilialization format (to avoid having the templatized version). I edited this example and run it. Writing the data has worked fine -- except for the base_class serialization which needed an nvp -- but reading it causes a memory/segmentation fault problem. The same error happens with a binary archive. Using a text archive works fine. I'm new to boost serialization and debugging the code did not help me a lot. Is there anything specific to the serialization of base classes or abstract classes with the polymorphic XML format which needs to be handled? Or is this related to the serialization of pointers to the base class. Thanks for your help. Best Regards, Fadhel BA Here is the code I'm using: ( I removed some comments to make the code shorter) /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 // demo.cpp #include <cstddef> // NULL #include <iomanip> #include <iostream> #include <fstream> #include <string> #include <boost/archive/polymorphic_iarchive.hpp> #include <boost/archive/polymorphic_oarchive.hpp> #include <boost/archive/polymorphic_xml_iarchive.hpp> #include <boost/archive/polymorphic_xml_oarchive.hpp> #include <boost/archive/polymorphic_binary_iarchive.hpp> #include <boost/archive/polymorphic_binary_oarchive.hpp> #include <boost/archive/polymorphic_text_iarchive.hpp> #include <boost/archive/polymorphic_text_oarchive.hpp> #include <boost/serialization/base_object.hpp> #include <boost/serialization/utility.hpp> #include <boost/serialization/list.hpp> #include <boost/serialization/assume_abstract.hpp> #include <boost/serialization/nvp.hpp> ///////////////////////////////////////////////////////////// // gps coordinate // // llustrates serialization for a simple type // class gps_position { friend std::ostream & operator<<(std::ostream &os, const gps_position &gp); friend class boost::serialization::access; int degrees; int minutes; float seconds; void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int /* file_version */) const { ar << BOOST_SERIALIZATION_NVP(degrees); ar << BOOST_SERIALIZATION_NVP(minutes); ar << BOOST_SERIALIZATION_NVP(seconds); } void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int /* file_version */) { ar >> BOOST_SERIALIZATION_NVP(degrees); ar >> BOOST_SERIALIZATION_NVP(minutes); ar >> BOOST_SERIALIZATION_NVP(seconds); } public: // every serializable class needs a constructor gps_position(){}; gps_position(int _d, int _m, float _s) : degrees(_d), minutes(_m), seconds(_s) {} }; std::ostream & operator<<(std::ostream &os, const gps_position &gp) { return os << ' ' << gp.degrees << (unsigned char)186 << gp.minutes << '\'' << gp.seconds << '"'; } ///////////////////////////////////////////////////////////// // One bus stop // // illustrates serialization of serializable members // class bus_stop { friend class boost::serialization::access; friend std::ostream & operator<<(std::ostream &os, const bus_stop &gp); virtual std::string description() const = 0; gps_position latitude; gps_position longitude; void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int version) const { ar << BOOST_SERIALIZATION_NVP(latitude); ar << BOOST_SERIALIZATION_NVP(longitude); } void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int version) { ar >> BOOST_SERIALIZATION_NVP(latitude); ar >> BOOST_SERIALIZATION_NVP(longitude); } protected: bus_stop(const gps_position & _lat, const gps_position & _long) : latitude(_lat), longitude(_long) {} public: bus_stop(){} virtual ~bus_stop(){} }; BOOST_SERIALIZATION_ASSUME_ABSTRACT(bus_stop) std::ostream & operator<<(std::ostream &os, const bus_stop &bs) { return os << bs.latitude << bs.longitude << ' ' << bs.description(); } ///////////////////////////////////////////////////////////// // Several kinds of bus stops // // illustrates serialization of derived types // class bus_stop_corner : public bus_stop { friend class boost::serialization::access; std::string street1; std::string street2; virtual std::string description() const { return street1 + " and " + street2; } void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int version) const { // save/load base class information ar << boost::serialization::make_nvp("base", boost::serialization::base_object<bus_stop>(*this)); ar << BOOST_SERIALIZATION_NVP(street1); ar << BOOST_SERIALIZATION_NVP(street2);; } void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int version) { // save/load base class information ar >> boost::serialization::make_nvp("base", boost::serialization::base_object<bus_stop>(*this)); ar >> BOOST_SERIALIZATION_NVP(street1); ar >> BOOST_SERIALIZATION_NVP(street2); } public: bus_stop_corner(){} bus_stop_corner(const gps_position & _lat, const gps_position & _long, const std::string & _s1, const std::string & _s2 ) : bus_stop(_lat, _long), street1(_s1), street2(_s2) { } }; class bus_stop_destination : public bus_stop { friend class boost::serialization::access; std::string name; virtual std::string description() const { return name; } void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int version) const { ar << boost::serialization::make_nvp("base", boost::serialization::base_object<bus_stop>(*this)); ar << BOOST_SERIALIZATION_NVP(name); } void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int version) { ar >> boost::serialization::make_nvp("base", boost::serialization::base_object<bus_stop>(*this)); ar >> BOOST_SERIALIZATION_NVP(name); } public: bus_stop_destination(){} bus_stop_destination( const gps_position & _lat, const gps_position & _long, const std::string & _name ) : bus_stop(_lat, _long), name(_name) { } }; ///////////////////////////////////////////////////////////// // a bus route is a collection of bus stops // // illustrates serialization of STL collection templates. // // illustrates serialzation of polymorphic pointer (bus stop *); // class bus_route { friend class boost::serialization::access; friend std::ostream & operator<<(std::ostream &os, const bus_route &br); typedef bus_stop * bus_stop_pointer; std::list<bus_stop_pointer> stops; void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int version) const { // in this program, these classes are never serialized directly but rather // through a pointer to the base class bus_stop. So we need a way to be // sure that the archive contains information about these derived classes. //ar.template register_type<bus_stop_corner>(); ar.register_type(static_cast<bus_stop_corner *>(NULL)); //ar.template register_type<bus_stop_destination>(); ar.register_type(static_cast<bus_stop_destination *>(NULL)); // serialization of stl collections is already defined // in the header ar << BOOST_SERIALIZATION_NVP(stops); } void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int version) { ar.register_type(static_cast<bus_stop_corner *>(NULL)); ar.register_type(static_cast<bus_stop_destination *>(NULL)); // in the header ar >> BOOST_SERIALIZATION_NVP(stops); } public: bus_route(){} void append(bus_stop *_bs) { stops.insert(stops.end(), _bs); } }; std::ostream & operator<<(std::ostream &os, const bus_route &br) { std::list<bus_stop *>::const_iterator it; // note: we're displaying the pointer to permit verification // that duplicated pointers are properly restored. for(it = br.stops.begin(); it != br.stops.end(); it++){ os << '\n' << std::hex << "0x" << *it << std::dec << ' ' << **it; } return os; } ///////////////////////////////////////////////////////////// // a bus schedule is a collection of routes each with a starting time class bus_schedule { public: // note: this structure was made public. because the friend declarations // didn't seem to work as expected. struct trip_info { void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int file_version) const { // in versions 2 or later if(file_version >= 2) // read the drivers name ar << BOOST_SERIALIZATION_NVP(driver); // all versions have the follwing info ar << BOOST_SERIALIZATION_NVP(hour); ar << BOOST_SERIALIZATION_NVP(minute); } void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int file_version) { // in versions 2 or later if(file_version >= 2) // read the drivers name ar >> BOOST_SERIALIZATION_NVP(driver); // all versions have the follwing info ar >> BOOST_SERIALIZATION_NVP(hour); ar >> BOOST_SERIALIZATION_NVP(minute); } // starting time int hour; int minute; // only after system shipped was the driver's name added to the class std::string driver; trip_info(){} trip_info(int _h, int _m, const std::string &_d) : hour(_h), minute(_m), driver(_d) {} }; private: friend class boost::serialization::access; friend std::ostream & operator<<(std::ostream &os, const bus_schedule &bs); friend std::ostream & operator<<(std::ostream &os, const bus_schedule::trip_info &ti); std::list<std::pair<trip_info, bus_route *> > schedule; void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int version) const { ar << BOOST_SERIALIZATION_NVP(schedule); } void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int version) { ar >> BOOST_SERIALIZATION_NVP(schedule); } public: void append(const std::string &_d, int _h, int _m, bus_route *_br) { schedule.insert(schedule.end(), std::make_pair(trip_info(_h, _m, _d), _br)); } bus_schedule(){} }; BOOST_CLASS_VERSION(bus_schedule, 2) std::ostream & operator<<(std::ostream &os, const bus_schedule::trip_info &ti) { return os << '\n' << ti.hour << ':' << ti.minute << ' ' << ti.driver << ' '; } std::ostream & operator<<(std::ostream &os, const bus_schedule &bs) { std::list<std::pair<bus_schedule::trip_info, bus_route *>
::const_iterator it; for(it = bs.schedule.begin(); it != bs.schedule.end(); it++){ os << it->first << *(it->second); } return os; }
void save_schedule(const bus_schedule &s, const char * filename){ // make an archive std::ofstream ofs(filename); boost::archive::polymorphic_xml_oarchive oa(ofs); oa << s; } void restore_schedule(bus_schedule &s, const char * filename) { // open the archive std::ifstream ifs(filename); boost::archive::polymorphic_xml_iarchive ia(ifs); // restore the schedule from the archive ia >> s; } int main(int argc, char *argv[]) { // make the schedule bus_schedule original_schedule; // fill in the data // make a few stops bus_stop *bs0 = new bus_stop_corner( gps_position(34, 135, 52.560f), gps_position(134, 22, 78.30f), "24th Street", "10th Avenue" ); bus_stop *bs1 = new bus_stop_corner( gps_position(35, 137, 23.456f), gps_position(133, 35, 54.12f), "State street", "Cathedral Vista Lane" ); bus_stop *bs2 = new bus_stop_destination( gps_position(35, 136, 15.456f), gps_position(133, 32, 15.300f), "White House" ); bus_stop *bs3 = new bus_stop_destination( gps_position(35, 134, 48.789f), gps_position(133, 32, 16.230f), "Lincoln Memorial" ); // make a routes bus_route route0; route0.append(bs0); route0.append(bs1); route0.append(bs2); // add trips to schedule original_schedule.append("bob", 6, 24, &route0); original_schedule.append("bob", 9, 57, &route0); original_schedule.append("alice", 11, 02, &route0); // make aother routes bus_route route1; route1.append(bs3); route1.append(bs2); route1.append(bs1); // add trips to schedule original_schedule.append("ted", 7, 17, &route1); original_schedule.append("ted", 9, 38, &route1); original_schedule.append("alice", 11, 47, &route1); // display the complete schedule std::cout << "original schedule"; std::cout << original_schedule; std::string filename("C:/Dev/XML"); filename += "/demofile.xml"; // save the schedule save_schedule(original_schedule, filename.c_str()); // ... some time later // make a new schedule bus_schedule new_schedule; std::cout << "\n\nstarting restored schedule"; restore_schedule(new_schedule, filename.c_str()); // and display std::cout << "\nrestored schedule"; std::cout << new_schedule; // should be the same as the old one. (except for the pointer values) delete bs0; delete bs1; delete bs2; delete bs3; return 0; }
Fadhel wrote:
Hi all,
I used http://www.boost.org/doc/libs/1_53_0/libs/serialization/example/demo.cpp file as a first introduction to boost serialization. I would like to use polymorphic archives with XML serilialization format (to avoid having the templatized version). I edited this example and run it. Writing the data has worked fine -- except for the base_class serialization which needed an nvp -- but reading it causes a memory/segmentation fault problem. The same error happens with a binary archive. Using a text archive works fine. I'm new to boost serialization and debugging the code did not help me a lot.
Note that there are specific tests/examples for using polymorphic archives. They might not be mentioned in the documentation. Look in the examples and test directories.
Is there anything specific to the serialization of base classes or abstract classes with the polymorphic XML format which needs to be handled? Or is this related to the serialization of pointers to the base class.
Try making the following changes below. These mirror the more common way that the polymorphic archives would be used. The whole idea is to delay the actual serialization archive selection until runtime.
Thanks for your help. Best Regards, Fadhel BA
Here is the code I'm using: ( I removed some comments to make the code shorter)
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 // demo.cpp #include <cstddef> // NULL #include <iomanip> #include <iostream> #include <fstream> #include <string>
#include <boost/archive/polymorphic_iarchive.hpp> #include <boost/archive/polymorphic_oarchive.hpp> #include <boost/archive/polymorphic_xml_iarchive.hpp> #include <boost/archive/polymorphic_xml_oarchive.hpp> #include <boost/archive/polymorphic_binary_iarchive.hpp> #include <boost/archive/polymorphic_binary_oarchive.hpp> #include <boost/archive/polymorphic_text_iarchive.hpp> #include <boost/archive/polymorphic_text_oarchive.hpp>
#include <boost/serialization/base_object.hpp> #include <boost/serialization/utility.hpp> #include <boost/serialization/list.hpp> #include <boost/serialization/assume_abstract.hpp> #include <boost/serialization/nvp.hpp>
///////////////////////////////////////////////////////////// // gps coordinate // // llustrates serialization for a simple type // class gps_position { friend std::ostream & operator<<(std::ostream &os, const gps_position &gp); friend class boost::serialization::access; int degrees; int minutes; float seconds;
void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int /* file_version */) const { ar << BOOST_SERIALIZATION_NVP(degrees); ar << BOOST_SERIALIZATION_NVP(minutes); ar << BOOST_SERIALIZATION_NVP(seconds); }
void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int /* file_version */) { ar >> BOOST_SERIALIZATION_NVP(degrees); ar >> BOOST_SERIALIZATION_NVP(minutes); ar >> BOOST_SERIALIZATION_NVP(seconds); } public: // every serializable class needs a constructor gps_position(){}; gps_position(int _d, int _m, float _s) : degrees(_d), minutes(_m), seconds(_s) {}
};
std::ostream & operator<<(std::ostream &os, const gps_position &gp) { return os << ' ' << gp.degrees << (unsigned char)186 << gp.minutes << '\'' << gp.seconds << '"'; }
///////////////////////////////////////////////////////////// // One bus stop // // illustrates serialization of serializable members //
class bus_stop { friend class boost::serialization::access; friend std::ostream & operator<<(std::ostream &os, const bus_stop &gp); virtual std::string description() const = 0; gps_position latitude; gps_position longitude;
void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int version) const { ar << BOOST_SERIALIZATION_NVP(latitude); ar << BOOST_SERIALIZATION_NVP(longitude); }
void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int version) { ar >> BOOST_SERIALIZATION_NVP(latitude); ar >> BOOST_SERIALIZATION_NVP(longitude); } protected: bus_stop(const gps_position & _lat, const gps_position & _long) : latitude(_lat), longitude(_long) {} public: bus_stop(){} virtual ~bus_stop(){} };
BOOST_SERIALIZATION_ASSUME_ABSTRACT(bus_stop)
std::ostream & operator<<(std::ostream &os, const bus_stop &bs) { return os << bs.latitude << bs.longitude << ' ' << bs.description(); }
///////////////////////////////////////////////////////////// // Several kinds of bus stops // // illustrates serialization of derived types // class bus_stop_corner : public bus_stop { friend class boost::serialization::access; std::string street1; std::string street2; virtual std::string description() const { return street1 + " and " + street2; }
void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int version) const { // save/load base class information ar << boost::serialization::make_nvp("base", boost::serialization::base_object<bus_stop>(*this)); ar << BOOST_SERIALIZATION_NVP(street1); ar << BOOST_SERIALIZATION_NVP(street2);; }
void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int version) { // save/load base class information ar >> boost::serialization::make_nvp("base", boost::serialization::base_object<bus_stop>(*this)); ar >> BOOST_SERIALIZATION_NVP(street1); ar >> BOOST_SERIALIZATION_NVP(street2); }
public: bus_stop_corner(){} bus_stop_corner(const gps_position & _lat, const gps_position & _long, const std::string & _s1, const std::string & _s2 ) : bus_stop(_lat, _long), street1(_s1), street2(_s2) { } };
class bus_stop_destination : public bus_stop { friend class boost::serialization::access; std::string name; virtual std::string description() const { return name; }
void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int version) const { ar << boost::serialization::make_nvp("base", boost::serialization::base_object<bus_stop>(*this)); ar << BOOST_SERIALIZATION_NVP(name); }
void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int version) { ar >> boost::serialization::make_nvp("base", boost::serialization::base_object<bus_stop>(*this)); ar >> BOOST_SERIALIZATION_NVP(name); } public:
bus_stop_destination(){} bus_stop_destination( const gps_position & _lat, const gps_position & _long, const std::string & _name ) : bus_stop(_lat, _long), name(_name) { } };
///////////////////////////////////////////////////////////// // a bus route is a collection of bus stops // // illustrates serialization of STL collection templates. // // illustrates serialzation of polymorphic pointer (bus stop *); //
class bus_route { friend class boost::serialization::access; friend std::ostream & operator<<(std::ostream &os, const bus_route &br); typedef bus_stop * bus_stop_pointer; std::list<bus_stop_pointer> stops;
void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int version) const { // in this program, these classes are never serialized directly but rather // through a pointer to the base class bus_stop. So we need a way to be // sure that the archive contains information about these derived classes. //ar.template register_type<bus_stop_corner>(); ar.register_type(static_cast<bus_stop_corner *>(NULL)); //ar.template register_type<bus_stop_destination>(); ar.register_type(static_cast<bus_stop_destination *>(NULL)); // serialization of stl collections is already defined // in the header ar << BOOST_SERIALIZATION_NVP(stops); }
void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int version) {
ar.register_type(static_cast<bus_stop_corner *>(NULL)); ar.register_type(static_cast<bus_stop_destination *>(NULL)); // in the header ar >> BOOST_SERIALIZATION_NVP(stops); } public: bus_route(){} void append(bus_stop *_bs) { stops.insert(stops.end(), _bs); } };
std::ostream & operator<<(std::ostream &os, const bus_route &br) { std::list<bus_stop *>::const_iterator it; // note: we're displaying the pointer to permit verification // that duplicated pointers are properly restored. for(it = br.stops.begin(); it != br.stops.end(); it++){ os << '\n' << std::hex << "0x" << *it << std::dec << ' ' << **it; } return os; }
///////////////////////////////////////////////////////////// // a bus schedule is a collection of routes each with a starting time
class bus_schedule { public: // note: this structure was made public. because the friend declarations // didn't seem to work as expected. struct trip_info { void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int file_version) const { // in versions 2 or later if(file_version >= 2) // read the drivers name ar << BOOST_SERIALIZATION_NVP(driver); // all versions have the follwing info ar << BOOST_SERIALIZATION_NVP(hour); ar << BOOST_SERIALIZATION_NVP(minute); }
void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int file_version) { // in versions 2 or later if(file_version >= 2) // read the drivers name ar >> BOOST_SERIALIZATION_NVP(driver); // all versions have the follwing info ar >> BOOST_SERIALIZATION_NVP(hour); ar >> BOOST_SERIALIZATION_NVP(minute); }
// starting time int hour; int minute; // only after system shipped was the driver's name added to the class std::string driver;
trip_info(){} trip_info(int _h, int _m, const std::string &_d) : hour(_h), minute(_m), driver(_d) {} }; private: friend class boost::serialization::access; friend std::ostream & operator<<(std::ostream &os, const bus_schedule &bs); friend std::ostream & operator<<(std::ostream &os, const bus_schedule::trip_info &ti); std::list<std::pair<trip_info, bus_route *> > schedule;
void serialize(boost::archive::polymorphic_oarchive &ar, const unsigned int version) const { ar << BOOST_SERIALIZATION_NVP(schedule); }
void serialize(boost::archive::polymorphic_iarchive &ar, const unsigned int version) { ar >> BOOST_SERIALIZATION_NVP(schedule); } public: void append(const std::string &_d, int _h, int _m, bus_route *_br) { schedule.insert(schedule.end(), std::make_pair(trip_info(_h, _m, _d), _br)); } bus_schedule(){} };
BOOST_CLASS_VERSION(bus_schedule, 2)
std::ostream & operator<<(std::ostream &os, const bus_schedule::trip_info &ti) { return os << '\n' << ti.hour << ':' << ti.minute << ' ' << ti.driver << ' '; } std::ostream & operator<<(std::ostream &os, const bus_schedule &bs) { std::list<std::pair<bus_schedule::trip_info, bus_route *>
const_iterator it; for(it = bs.schedule.begin(); it != bs.schedule.end(); it++){ os << it->first << *(it->second); } return os; }
void save_schedule(const bus_schedule &s, const char * filename){ // make an archive std::ofstream ofs(filename);
// try the following.
//boost::archive::polymorphic_xml_oarchive oa(ofs);
boost::archive::polymorphic_oarchive & oa = boost::archive::polymorphic_xml_oarchive(ofs)
oa << s; }
void restore_schedule(bus_schedule &s, const char * filename) { // open the archive std::ifstream ifs(filename); //boost::archive::polymorphic_xml_iarchive ia(ifs);
boost::archive::polymorphic_iarchive & ia = boost::archive::polymorphic_xml_iarchive(ifs);
// restore the schedule from the archive ia >> s; }
int main(int argc, char *argv[]) { // make the schedule bus_schedule original_schedule;
// fill in the data // make a few stops bus_stop *bs0 = new bus_stop_corner( gps_position(34, 135, 52.560f), gps_position(134, 22, 78.30f), "24th Street", "10th Avenue" ); bus_stop *bs1 = new bus_stop_corner( gps_position(35, 137, 23.456f), gps_position(133, 35, 54.12f), "State street", "Cathedral Vista Lane" ); bus_stop *bs2 = new bus_stop_destination( gps_position(35, 136, 15.456f), gps_position(133, 32, 15.300f), "White House" ); bus_stop *bs3 = new bus_stop_destination( gps_position(35, 134, 48.789f), gps_position(133, 32, 16.230f), "Lincoln Memorial" );
// make a routes bus_route route0; route0.append(bs0); route0.append(bs1); route0.append(bs2);
// add trips to schedule original_schedule.append("bob", 6, 24, &route0); original_schedule.append("bob", 9, 57, &route0); original_schedule.append("alice", 11, 02, &route0);
// make aother routes bus_route route1; route1.append(bs3); route1.append(bs2); route1.append(bs1);
// add trips to schedule original_schedule.append("ted", 7, 17, &route1); original_schedule.append("ted", 9, 38, &route1); original_schedule.append("alice", 11, 47, &route1);
// display the complete schedule std::cout << "original schedule"; std::cout << original_schedule;
std::string filename("C:/Dev/XML"); filename += "/demofile.xml";
// save the schedule save_schedule(original_schedule, filename.c_str());
// ... some time later // make a new schedule bus_schedule new_schedule;
std::cout << "\n\nstarting restored schedule"; restore_schedule(new_schedule, filename.c_str());
// and display std::cout << "\nrestored schedule"; std::cout << new_schedule; // should be the same as the old one. (except for the pointer values) delete bs0; delete bs1; delete bs2; delete bs3; return 0; }
participants (2)
-
Fadhel
-
Robert Ramey