[serialization / shared_ptr] Problem to serialize a shared_ptr
Hi there, I am relatively new to Boost in general and serialization in particular. Nevertheless, having spent the day trying to find out how to serialize a shared_ptr, I feel it is time to search for some external advice. So any help is appreciated! Here is the (hopefully) simple program: /************************************************************/ #include <typeinfo> #include <fstream> #include <iostream> #include <sstream> #include <vector> #include <boost/shared_ptr.hpp> #include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/nvp.hpp> #include <boost/serialization/vector.hpp> // #include <boost/serialization/shared_ptr_132.hpp> #include <boost/serialization/shared_ptr.hpp> #include <boost/serialization/base_object.hpp> #include <boost/serialization/utility.hpp> #include <boost/serialization/export.hpp> #include <boost/serialization/tracking.hpp> using namespace std; using namespace boost; using namespace boost::serialization; class ptr{ friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version){ using boost::serialization::make_nvp; ar & make_nvp("p",p); } shared_ptr<int> p; public: ptr(){ shared_ptr<int> dummy(new int(6)); p = dummy; } void printInfo(void){ cout << "*(p.get()) = " << *(p.get()) << endl; } }; main() { ostringstream ofs; ptr myp; { boost::archive::xml_oarchive oa(ofs); oa << make_nvp("myp",myp); } cout << ofs.str() << endl; ptr newmyp; { istringstream ifs; ifs.str(ofs.str()); boost::archive::xml_iarchive ia(ifs); ia >> make_nvp("myp",newmyp); } newmyp.printInfo(); return 0; } /************************************************************/ When I try to compile this (OpenSUSE 10.2, g++ 4.1.2, Boost 1.33.1), I get a LONG list of error messages, of which I will only quote the first few lines only: /************************************************************/ $ g++ -o test14 -lboost_serialization test14.cc /usr/include/boost/serialization/shared_ptr.hpp: In function ‘void boost::serialization::serialize(Archive&, boost::shared_ptr<U>&, unsigned int) [with Archive = boost::archive::xml_iarchive, T = int]’: /usr/include/boost/serialization/serialization.hpp:140: instantiated from ‘void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::xml_iarchive, T = boost::shared_ptr<int>]’ /usr/include/boost/archive/detail/iserializer.hpp:160: instantiated from ‘void boost::archive::detail::iserializer<Archive, T>::load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const [with Archive = boost::archive::xml_iarchive, T = boost::shared_ptr<int>]’ test14.cc:73: instantiated from here /usr/include/boost/serialization/shared_ptr.hpp:235: error: invalid application of ‘sizeof’ to incomplete type ‘boost::STATIC_ASSERTION_FAILURE<false>’ [...] /************************************************************/ The "STATIC_ASSERTION_FAILURE appears quite often in the error messages. BTW, the program runs nicely, if I include a simple int as "data load" in this class (and modify the program to accept an int instead of a shared_ptr, of course). I'm therefore confident that most of the logic is just fine. Any help is appreciated! Best Regards, Ruediger
STATIC_ASSERTION_FAILURE indicates that some error condition has been detected at compile time. In all such cases, there is a comment indicating the likely cause of the error. I don't know which version of boost your using so I can't look for the comment for you - but I'm sure you can find it now you know what to look for. Looking at you code, I can see you're trying to serialize a shared pointer to an integer. addresses of prmitive types (int) are by default not tracked as doing so would end up tracking ALL the ints serialized which is not what most people would expect. if you want to do this you'll have to wrap the int in a class so its type can be distuished and it can then be tracked. Then I believe that serializing a pointer to your wrapped class will function as you hope and expect. Robert Ramey Ruediger Berlich wrote:
Hi there, I am relatively new to Boost in general and serialization in particular. Nevertheless, having spent the day trying to find out how to serialize a shared_ptr, I feel it is time to search for some external advice. So any help is appreciated!
Here is the (hopefully) simple program:
/************************************************************/
#include <typeinfo> #include <fstream> #include <iostream> #include <sstream> #include <vector> #include <boost/shared_ptr.hpp>
#include <boost/archive/xml_oarchive.hpp> #include <boost/archive/xml_iarchive.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/nvp.hpp> #include <boost/serialization/vector.hpp> // #include <boost/serialization/shared_ptr_132.hpp> #include <boost/serialization/shared_ptr.hpp> #include <boost/serialization/base_object.hpp> #include <boost/serialization/utility.hpp> #include <boost/serialization/export.hpp> #include <boost/serialization/tracking.hpp>
using namespace std; using namespace boost;
using namespace boost::serialization;
class ptr{ friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar, const unsigned int version){ using boost::serialization::make_nvp; ar & make_nvp("p",p); }
shared_ptr<int> p;
public: ptr(){ shared_ptr<int> dummy(new int(6)); p = dummy; }
void printInfo(void){ cout << "*(p.get()) = " << *(p.get()) << endl; }
};
main() { ostringstream ofs;
ptr myp;
{ boost::archive::xml_oarchive oa(ofs); oa << make_nvp("myp",myp); }
cout << ofs.str() << endl;
ptr newmyp;
{ istringstream ifs; ifs.str(ofs.str()); boost::archive::xml_iarchive ia(ifs); ia >> make_nvp("myp",newmyp); }
newmyp.printInfo();
return 0; }
/************************************************************/
When I try to compile this (OpenSUSE 10.2, g++ 4.1.2, Boost 1.33.1), I get a LONG list of error messages, of which I will only quote the first few lines only:
/************************************************************/ $ g++ -o test14 -lboost_serialization test14.cc /usr/include/boost/serialization/shared_ptr.hpp: In function 'void boost::serialization::serialize(Archive&, boost::shared_ptr<U>&, unsigned int) [with Archive = boost::archive::xml_iarchive, T = int]': /usr/include/boost/serialization/serialization.hpp:140: instantiated from 'void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::xml_iarchive, T = boost::shared_ptr<int>]' /usr/include/boost/archive/detail/iserializer.hpp:160: instantiated from 'void boost::archive::detail::iserializer<Archive,
load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const [with Archive = boost::archive::xml_iarchive, T = boost::shared_ptr<int>]' test14.cc:73: instantiated from here /usr/include/boost/serialization/shared_ptr.hpp:235: error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>' [...] /************************************************************/
The "STATIC_ASSERTION_FAILURE appears quite often in the error messages.
BTW, the program runs nicely, if I include a simple int as "data load" in this class (and modify the program to accept an int instead of a shared_ptr, of course). I'm therefore confident that most of the logic is just fine.
Any help is appreciated!
Best Regards, Ruediger
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Dear Robert, thanks a lot! I can now, without any larger problem, serialize a class with a signature similar to class myClass :public vector<shared_ptr<base> > {...}; which is what I wanted all along. "base" is a purely virtual class, and the vector holds objects derived directly or indirectly from base. So this is great! Still, I'm not too sure what the problem was with the shared_ptr<int> . The last line of the error messages says (and by the way, I'm using OpenSUSE 10.2, g++ 4.1.2, Boost 1.33.1): "/usr/include/boost/serialization/access.hpp:109: error: request for member serialize in t, which is of non-class type" Presumably this is the comment you mention ? This seems to indicate that the "driver" for the shared_ptr tried to treat the shared_ptr's template arguments as a class object with a method "serialize", which of course wouldn't work. How can I teach the library that this particular shared_ptr just holds a basic type ? Thanks a lot for your help, Ruediger P.S.: Björn Karlsson mentions you as the author of Boost.Serialization in his Boost book. So: congratulations - your library is great(!) work. Robert Ramey wrote:
STATIC_ASSERTION_FAILURE
indicates that some error condition has been detected at compile time.
In all such cases, there is a comment indicating the likely cause of the error. I don't know which version of boost your using so I can't look for the comment for you - but I'm sure you can find it now you know what to look for.
Looking at you code, I can see you're trying to serialize a shared pointer to an integer. addresses of prmitive types (int) are by default not tracked as doing so would end up tracking ALL the ints serialized which is not what most people would expect. if you want to do this you'll have to wrap the int in a class so its type can be distuished and it can then be tracked. Then I believe that serializing a pointer to your wrapped class will function as you hope and expect.
Robert Ramey
[... Original posting deleted - see archive ...]
Ruediger Berlich wrote:
How can I teach the library that this particular shared_ptr just holds a basic type ?
Looking at you code, I can see you're trying to serialize a shared pointer to an integer. addresses of prmitive types (int) are by default not tracked as doing so would end up tracking ALL the ints serialized which is not what most people would expect. if you want to do this you'll have to wrap the int in a class so its type can be distuished and it can then be tracked. Then I believe that serializing a pointer to your wrapped class will function as you hope and expect.
The issue tracking. We turn off tracking for prmitive types because it would be "too much". If yo want to override this for a particular case, make a small class/struct which holds and int and serialize a shared pointer to that. Robert Ramey
participants (2)
-
Robert Ramey
-
Ruediger Berlich