Serialization of boost::shared_ptr<int>?

Hi Robert and everyone, Thank you for explaining to me about BOOST_STRONGTYPE. I'll let you know how that goes for me. And thank you for being so patient and trying to help me get serialization working in my program. In the meantime, I'm experiencing a much simpler problem. Although I can serialize classes of the form boost::shared_ptr<T>, where T is a class I've defined, I get compilation errors if I try to serialize a boost::shared_ptr<int>. How can I resolve this? Code snippet: ----------------------------------------------- #include <iostream> #include <fstream> #include <boost/shared_ptr.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/base_object.hpp> #include <boost/serialization/utility.hpp> #include <boost/serialization/shared_ptr.hpp> int main() { std::ofstream ofs("archive"); boost::archive::text_oarchive oa(ofs); boost::shared_ptr<int> i; oa << i; return 0; } ----------------------------------------------- g++ output: /usr/include/boost/serialization/shared_ptr.hpp: In function `void boost::serialization::serialize(Archive&, boost::shared_ptr<U>&, unsigned int) [with Archive = boost::archive::text_oarchive, T = int]': /usr/include/boost/serialization/serialization.hpp:140: instantiated from `void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::shared_ptr<int>]' /usr/include/boost/archive/detail/oserializer.hpp:147: instantiated from `void boost::archive::detail::oserializer<Archive, T>::save_object_data(boost::archive::detail::basic_oarchive&, const void*) const [with Archive = boost::archive::text_oarchive, T = boost::shared_ptr<int>]' /usr/include/boost/mpl/if.hpp:67: instantiated from here /usr/include/boost/serialization/shared_ptr.hpp:227: error: incomplete type ` boost::STATIC_ASSERTION_FAILURE<false>' does not have member `value' /usr/include/boost/serialization/shared_ptr.hpp: In function `void boost::serialization::save(Archive&, const boost::shared_ptr<U>&, unsigned int) [with Archive = boost::archive::text_oarchive, T = int]': /usr/include/boost/serialization/split_free.hpp:45: instantiated from `static void boost::serialization::free_saver<Archive, T>::invoke(Archive&, const T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::shared_ptr<int>]' /usr/include/boost/serialization/split_free.hpp:74: instantiated from `void boost::serialization::split_free(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::shared_ptr<int>]' /usr/include/boost/serialization/shared_ptr.hpp:231: instantiated from `void boost::serialization::serialize(Archive&, boost::shared_ptr<U>&, unsigned int) [with Archive = boost::archive::text_oarchive, T = int]' /usr/include/boost/serialization/serialization.hpp:140: instantiated from `void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::shared_ptr<int>]' /usr/include/boost/archive/detail/oserializer.hpp:147: instantiated from `void boost::archive::detail::oserializer<Archive, T>::save_object_data(boost::archive::detail::basic_oarchive&, const void*) const [with Archive = boost::archive::text_oarchive, T = boost::shared_ptr<int>]' /usr/include/boost/mpl/if.hpp:67: instantiated from here /usr/include/boost/serialization/shared_ptr.hpp:183: error: incomplete type ` boost::STATIC_ASSERTION_FAILURE<false>' does not have member `value' /usr/include/boost/serialization/access.hpp: In static member function `static void boost::serialization::access::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = int]': /usr/include/boost/serialization/serialization.hpp:81: instantiated from `void boost::serialization::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = int]' /usr/include/boost/serialization/serialization.hpp:140: instantiated from `void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = int]' /usr/include/boost/archive/detail/oserializer.hpp:232: instantiated from `boost::archive::detail::pointer_oserializer<T, Archive>::pointer_oserializer() [with T = int, Archive = boost::archive::text_oarchive]' /usr/include/boost/archive/detail/oserializer.hpp:197: instantiated from `const boost::archive::detail::pointer_oserializer<int, boost::archive::text_oarchive> boost::archive::detail::pointer_oserializer<int, boost::archive::text_oarchive>::instance' /usr/include/boost/archive/detail/oserializer.hpp:189: instantiated from `static const boost::archive::detail::pointer_oserializer<T, Archive>& boost::archive::detail::pointer_oserializer<T, Archive>::instantiate() [with T = int, Archive = boost::archive::text_oarchive]' /usr/include/boost/archive/detail/oserializer.hpp:514: instantiated from `const boost::archive::detail::basic_pointer_oserializer& boost::archive::detail::instantiate_pointer_oserializer(Archive*, T*) [with Archive = boost::archive::text_oarchive, T = int]' /usr/include/boost/archive/detail/interface_oarchive.hpp:65: instantiated from `const boost::archive::detail::basic_pointer_oserializer* boost::archive::detail::interface_oarchive<Archive>::register_type(const T*) [with T = int, Archive = boost::archive::text_oarchive]' /usr/include/boost/archive/detail/oserializer.hpp:343: instantiated from `static const boost::archive::detail::basic_pointer_oserializer* boost::archive::detail::save_pointer_type<Archive, TPtr>::non_abstract<T>::register_type(Archive&) [with T = const int, Archive = boost::archive::text_oarchive, TPtr = const int*]' /usr/include/boost/archive/detail/oserializer.hpp:359: instantiated from `static const boost::archive::detail::basic_pointer_oserializer* boost::archive::detail::save_pointer_type<Archive, TPtr>::register_type(Archive&, T&) [with T = const int, Archive = boost::archive::text_oarchive, TPtr = const int*]' /usr/include/boost/archive/detail/oserializer.hpp:459: instantiated from `static void boost::archive::detail::save_pointer_type<Archive, TPtr>::invoke(Archive&, TPtr) [with Archive = boost::archive::text_oarchive, TPtr = const int*]' /usr/include/boost/archive/detail/oserializer.hpp:535: instantiated from `void boost::archive::save(Archive&, const T&) [with Archive = boost::archive::text_oarchive, T = const int*]' /usr/include/boost/archive/basic_text_oarchive.hpp:78: instantiated from `void boost::archive::basic_text_oarchive<Archive>::save_override(T&, int) [with T = const int* const, Archive = boost::archive::text_oarchive]' /usr/include/boost/archive/detail/interface_oarchive.hpp:85: instantiated from `Archive& boost::archive::detail::interface_oarchive<Archive>::operator<<(T&) [with T = const int* const, Archive = boost::archive::text_oarchive]' /usr/include/boost/serialization/nvp.hpp:77: instantiated from `void boost::serialization::nvp<T>::save(Archivex&, unsigned int) const [with Archivex = boost::archive::text_oarchive, T = const int*]' /usr/include/boost/serialization/access.hpp:93: instantiated from `static void boost::serialization::access::member_save(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = const boost::serialization::nvp<const int*>]' /usr/include/boost/serialization/split_member.hpp:43: instantiated from `static void boost::serialization::detail::member_saver<Archive, T>::invoke(Archive&, const T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::serialization::nvp<const int*>]' /usr/include/boost/serialization/split_member.hpp:69: instantiated from `void boost::serialization::split_member(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::serialization::nvp<const int*>]' /usr/include/boost/serialization/nvp.hpp:87: instantiated from `void boost::serialization::nvp<T>::serialize(Archive&, unsigned int) [with Archive = boost::archive::text_oarchive, T = const int*]' /usr/include/boost/serialization/access.hpp:109: instantiated from `static void boost::serialization::access::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::serialization::nvp<const int*>]' /usr/include/boost/serialization/serialization.hpp:81: instantiated from `void boost::serialization::serialize(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::serialization::nvp<const int*>]' /usr/include/boost/serialization/serialization.hpp:140: instantiated from `void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::serialization::nvp<const int*>]' /usr/include/boost/archive/detail/oserializer.hpp:252: instantiated from `static void boost::archive::detail::save_non_pointer_type<Archive, T>::save_only::invoke(Archive&, const T&) [with Archive = boost::archive::text_oarchive, T = boost::serialization::nvp<const int*>]' /usr/include/boost/archive/detail/oserializer.hpp:321: instantiated from `static void boost::archive::detail::save_non_pointer_type<Archive, T>::invoke(Archive&, const T&) [with Archive = boost::archive::text_oarchive, T = boost::serialization::nvp<const int*>]' /usr/include/boost/archive/detail/oserializer.hpp:535: instantiated from `void boost::archive::save(Archive&, const T&) [with Archive = boost::archive::text_oarchive, T = boost::serialization::nvp<const int*>]' /usr/include/boost/archive/basic_text_oarchive.hpp:78: instantiated from `void boost::archive::basic_text_oarchive<Archive>::save_override(T&, int) [with T = const boost::serialization::nvp<const int*>, Archive = boost::archive::text_oarchive]' /usr/include/boost/archive/detail/interface_oarchive.hpp:85: instantiated from `Archive& boost::archive::detail::interface_oarchive<Archive>::operator<<(T&) [with T = const boost::serialization::nvp<const int*>, Archive = boost::archive::text_oarchive]' /usr/include/boost/serialization/shared_ptr.hpp:185: instantiated from `void boost::serialization::save(Archive&, const boost::shared_ptr<U>&, unsigned int) [with Archive = boost::archive::text_oarchive, T = int]' /usr/include/boost/serialization/split_free.hpp:45: instantiated from `static void boost::serialization::free_saver<Archive, T>::invoke(Archive&, const T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::shared_ptr<int>]' /usr/include/boost/serialization/split_free.hpp:74: instantiated from `void boost::serialization::split_free(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::shared_ptr<int>]' /usr/include/boost/serialization/shared_ptr.hpp:231: instantiated from `void boost::serialization::serialize(Archive&, boost::shared_ptr<U>&, unsigned int) [with Archive = boost::archive::text_oarchive, T = int]' /usr/include/boost/serialization/serialization.hpp:140: instantiated from `void boost::serialization::serialize_adl(Archive&, T&, unsigned int) [with Archive = boost::archive::text_oarchive, T = boost::shared_ptr<int>]' /usr/include/boost/archive/detail/oserializer.hpp:147: instantiated from `void boost::archive::detail::oserializer<Archive, T>::save_object_data(boost::archive::detail::basic_oarchive&, const void*) const [with Archive = boost::archive::text_oarchive, T = boost::shared_ptr<int>]' /usr/include/boost/mpl/if.hpp:67: instantiated from here /usr/include/boost/serialization/access.hpp:109: error: request for member ` serialize' in `t', which is of non-aggregate type `int' ----------------------------------------------- Thanks again for being so helpful! Joseph -- http://www.cs.nyu.edu/~turian/

Joseph schrieb:
In the meantime, I'm experiencing a much simpler problem. Although I can serialize classes of the form boost::shared_ptr<T>, where T is a class I've defined, I get compilation errors if I try to serialize a boost::shared_ptr<int>.
How can I resolve this?
In such error messages, the first thing to look at is where the actual error happens, indicated by gcc with "instantiated for here". You'll find it's a static assertion and along with it the comment: // The most common cause of trapping here would be serializing // something like shared_ptr<int>. This occurs because int // is never tracked by default. Wrap int in a trackable type As you can then look up in the documentation, for ints the address is not serialised, as their tracking traits default to track_never, which is probably sensible. Simply wrap you int in your own class, then you are fine. And this is as efficient. Jens

Try the following change - If this does it - read the rationale about using const with serialization. Robert Ramey Joseph Turian wrote:
Hi Robert and everyone,
Thank you for explaining to me about BOOST_STRONGTYPE. I'll let you know how that goes for me. And thank you for being so patient and trying to help me get serialization working in my program.
In the meantime, I'm experiencing a much simpler problem. Although I can serialize classes of the form boost::shared_ptr<T>, where T is a class I've defined, I get compilation errors if I try to serialize a boost::shared_ptr<int>.
How can I resolve this?
Code snippet: ----------------------------------------------- #include <iostream> #include <fstream>
#include <boost/shared_ptr.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/base_object.hpp> #include <boost/serialization/utility.hpp> #include <boost/serialization/shared_ptr.hpp>
int main() { std::ofstream ofs("archive"); boost::archive::text_oarchive oa(ofs);
//boost::shared_ptr<int> i; const boost::shared_ptr<int> i; oa << i;
return 0; } -----------------------------------------------

Try the following change - If this does it - read the rationale about using const with serialization.
Unfortunately this doesn't change the compiler errors output at all. Can you duplicate this bad behavior on your system? Joseph -- http://www.cs.nyu.edu/~turian/

I compiled the following program on my system #include <fstream> #include <boost/archive/text_oarchive.hpp> #include <boost/serialization/shared_ptr.hpp> int main() { std::ofstream ofs("archive"); boost::archive::text_oarchive oa(ofs); const boost::shared_ptr<int> i; oa << i; return 0; } The first syntax error I got was: test_zmisc.cpp c:\BoostMainCVS\libs\serialization\vc7ide\..\..\..\boost\serialization\shared_ptr.hpp(231) : error C2027: use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>' ... In my vc 7.1 system I double click on this error and I am displayed the following source line from boost/serialization/shared_ptr.hpp // correct shared_ptr serialization depends upon object tracking // being used. BOOST_STATIC_ASSERT( boost::serialization::tracking_level<T>::value != boost::serialization::track_never ); .... This indicates the the serialization of shared_ptr<T> is only implemented if T is a tracked type. So if you want to do this, there are a couple of options a) alter shared_ptr<T> to handle untracked types. This is probably not a great ideas as usually untracked types are untracked for a good reason. There are other reasons as well but we needn't go into them here. b) use BOOST_STRONG_TYPE to make an integer type that is tracked. This is what I recommend as its an unusual case an altering shared pointer serialization would be a pain in the neck and could easily have unexpected side-effects by implementing tracking as a global side-effect for types which otherwise would expeced to be untracked (like int) So, using b) Your program looks like: #include <fstream> #include <boost/archive/text_oarchive.hpp> #include <boost/serialization/shared_ptr.hpp> #include <boost/strong_typedef.hpp> // defined a "special kind of integer" BOOST_STRONG_TYPEDEF(int, tracked_int) // define serialization for a tracked int template<class Archive> void serialize(Archive &ar, tracked_int & ti, const unsigned int version){ // serialize the underlying int ar & static_cast<int &>(ti); } int main() { std::ofstream ofs("archive"); boost::archive::text_oarchive oa(ofs); const boost::shared_ptr<tracked_int> i; oa << i; return 0; } This program does in fact compile on my vc 7.1 system. I hope that answers your question. Good Luck Robert Ramey Joseph Turian wrote:
Try the following change - If this does it - read the rationale about using const with serialization.
Unfortunately this doesn't change the compiler errors output at all. Can you duplicate this bad behavior on your system?
Joseph

b) use BOOST_STRONG_TYPE to make an integer type that is tracked.
Okay. The code snippet you gave me worked great. However, I am now experiencing what I hope is the final problem. Basically, I have a recursive data structure A, which contains pointers of type boost::smart_pointer<A>. Could you please show me how to get the follow code snippet to work? I should say that I'm really appreciative for all your help. -------- #include <iostream> #include <fstream> #include <boost/shared_ptr.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/base_object.hpp> #include <boost/serialization/utility.hpp> #include <boost/serialization/shared_ptr.hpp> #include <boost/serialization/tracking.hpp> #include <boost/strong_typedef.hpp> class A; BOOST_STRONG_TYPEDEF(boost::shared_ptr<A>, Aptr) class A { public: friend class boost::serialization::access; template<class Archive> void serialize(Archive& ar, const unsigned int version) { ar & aptr; } private: Aptr aptr; }; template <class Archive> void serialize(Archive &ar, Aptr &aptr, const unsigned int version) { ar & static_cast<boost::shared_ptr<A> >(aptr); } int main() { std::ofstream ofs("archive"); boost::archive::text_oarchive oa(ofs); A a; oa << a; Aptr aptr; oa << aptr; return 0; } -------- Thanks! Joseph -- http://www.cs.nyu.edu/~turian/

I can't see what you're trying to do here. The following would seem to be equivalent to your intention #include <fstream> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/shared_ptr.hpp> class A { public: friend class boost::serialization::access; template<class Archive> void serialize( Archive& ar, const unsigned int version ) { ar & aptr; } private: A * aptr; }; int main() { std::ofstream ofs("archive"); boost::archive::text_oarchive oa(ofs); const A a; oa << a; return 0; } It doesn't do anything useful but it does compile. I think you would find that spending some more time with the documentation and the examples would be a good investment. Robert Ramey

I can't see what you're trying to do here.
The sample I provided is basically the simplest version of my code that, nonetheless, will not compile. In my code, it's much more complicated. Basically, I have class A, and class A has static member variables that are STL containers containing objects of type boost::shared_ptr<A>. But I tried to simplify it as much as possible to the basic piece which will not compile, which is what I provided in my last message. I suspect that if I could get the sample code (where A contains Aptr) working, then I'd be able to get my entire program serialized.
The following would seem to be equivalent to your intention
Unfortunately, I have to use smart_ptr's. Otherwise, managing object deletion will be extremely complicated.
I think you would find that spending some more time with the documentation and the examples would be a good investment.
I agree; I'm trying to understand the serialization library better so that I can answer my own questions. Nonetheless, if you are able to suggest a way to get serialization to work with class A containing static member variables of type boost::shared_ptr<A>, I'd be most appreciative. Thanks for your help so far. Best, Joseph -- http://www.cs.nyu.edu/~turian/

Joseph Turian wrote:
I can't see what you're trying to do here.
The sample I provided is basically the simplest version of my code that, nonetheless, will not compile.
In my code, it's much more complicated. Basically, I have class A, and class A has static member variables that are STL containers containing objects of type boost::shared_ptr<A>. But I tried to simplify it as much as possible to the basic piece which will not compile, which is what I provided in my last message.
I suspect that if I could get the sample code (where A contains Aptr) working, then I'd be able to get my entire program serialized.
Hmmm There are at least 3 totally orthogonal issues here. a) Serialization of static variables. This is handled the same as any other variables. Tracking can be used to ensure that only unique copies of the variables are serialized. b) Serialization of smart_ptr<int>. This would handled like seriliazation of another other type of smart pointer - except smart_ptr<T> can only be serialized if T is a tracked type. I showed how to use BOOST_STRONG_TYPE to make a type equivalent to an int which can be tracked and therefore be used as an argument to a serialized smart_ptr. c) Serializiation of contained pointers. This is common case handled by the library. The library considers and handles correctly the case where pointers are cyclic. I modified your code to show it compiles. (note there is also a test for cyclic pointers. I'm not aware of any other obstacles to doing what you want to do. Robert Ramey

There are at least 3 totally orthogonal issues here.
Yes, thank you for breaking it down. I believe we've isolated the trickiness to c)
a) Serialization of static variables. This is handled the same as any other variables. Tracking can be used to ensure that only unique copies of the variables are serialized.
I don't think this will be difficult for me to implement.
b) Serialization of smart_ptr<int>. This would handled like seriliazation of another other type of smart pointer - except smart_ptr<T> can only be serialized if T is a tracked type. I showed how to use BOOST_STRONG_TYPE to make a type equivalent to an int which can be tracked and therefore be used as an argument to a serialized smart_ptr.
Yes, thank you for explaining that for me.
c) Serializiation of contained pointers. This is common case handled by the library. The library considers and handles correctly the case where pointers are cyclic. I modified your code to show it compiles. (note there is also a test for cyclic pointers.)
Well, I see how your example compiles in the case of RAW cyclic pointers. However, I cannot use raw pointers, and I don't know how to get it to compile with cyclic smart pointers (specifically, boost::shared_ptr). Was there something that I missed? Thanks, Joseph -- http://www.cs.nyu.edu/~turian/

Well, I see how your example compiles in the case of RAW cyclic pointers. However, I cannot use raw pointers, and I don't know how to get it to compile with cyclic smart pointers (specifically, boost::shared_ptr). Was there something that I missed?
Just use a smart pointer instead of a raw pointer. The following compiles as expected. #include <fstream> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/shared_ptr.hpp> class A { public: friend class boost::serialization::access; template<class Archive> void serialize( Archive& ar, const unsigned int version ) { ar & aptr; } private: boost::shared_ptr<A> aptr; }; int main() { std::ofstream ofs("archive"); boost::archive::text_oarchive oa(ofs); const A a; oa << a; return 0; }

Hey boost users, I've hit what I figure is a compiler bug with release 1.33.1 under gcc 3.2, I'm trying to come up with a workaround. I modified test_exported.cpp from the serialization test suite to serialize via shared_ptr<polymorphic_base> to base rather than polymorphic_base*, and I've verified that the test runs fine on several platforms with gcc 4.0 and 3.4, but fails with 3.2. I'd love to just abandon 3.2, but unfortunately the hosts that require it are (literally) at the South Pole. The error reported is: execute-test ../../../bin/boost/libs/serialization/test/test_exported_binary_archive.test/gcc/debug/test_exported_binary_archive.run ====== BEGIN OUTPUT ====== test_exported_binary_archive: /icework/troy/boost_1_33_1/libs/serialization/src/basic_iarchive.cpp:466: const boost::archive::detail::basic_pointer_iserializer* boost::archive::detail::basic_iarchive_impl::load_pointer(boost::archive::detail::basic_iarchive&, void*&, const boost::archive::detail::basic_pointer_iserializer*, const boost::archive::detail::basic_pointer_iserializer*(*)(const boost::serialization::extended_type_info&)): Assertion `new_cid == cid' failed. Running 1 test case... unknown location(0): fatal error in "test_main_caller( argc, argv )": signal: SIGABRT (application abort requested) *** errors detected in test suite "Test Program"; see standard output for details EXIT STATUS: 200 ====== END OUTPUT ====== Which indicates that something has gone wrong with registration, it seems. One can toggle the buggy behavior by removing BOOST_IS_ABSTRACT(polymorphic_base). Whether polymorphic_base actually has a pure virtual function doesn't influence whether the error appears or not. I'm going to keep digging, but I thought I'd ask if this rings a bell with anyone. Modified test_exported.cpp attached. Thanks in advance, -t

troy d. straszheim wrote:
Which indicates that something has gone wrong with registration, it seems. One can toggle the buggy behavior by removing BOOST_IS_ABSTRACT(polymorphic_base). Whether polymorphic_base actually has a pure virtual function doesn't influence whether the error appears or not.
Note that "is_abstract" has had sort of history regarding serialization. Speaking from memory, boost::serialization::is_abstract punts to the official boost::is_abstract on platforms which support it and defaults to false on platforms that don't. This was arrived at in sort of an ad hoc fashion so it may be that there is something to be fixed there. Good Luck with this. Robert Ramey p.s. any chance of getting a business trip to the south pole out of this? RR
participants (4)
-
Joseph Turian
-
jth01@arcor.de
-
Robert Ramey
-
troy d. straszheim