
Robert Ramey wrote:
I thought about a little more. If I rememeber correctly the essense of the problem during de-serialization was:
template<class Archive, class T> void serialize(Archive &ar, shared_ptr<T> & t){ T * raw_ptr; ar >> raw_ptr; t = shared_ptr(raw_ptr); // problem is here - not matched with other shared pointers that might point to raw_ptr // current shared_ptr implementation depends upon an internal pointer to a shared count. }
No, the problems lie elsewhere. The pseudocode of the deserializer is as follows: typedef std::map< int, shared_ptr<void> > load_sp_map; template<class Archive, class T> void load(Archive & ar, shared_ptr<T> & t) { int pid; ar >> pid; if( pid == 0 ) { t.reset(); } else { load_sp_map & map = get_load_sp_map( ar ); // #1 if( map.count(pid) ) { t = convert_from_derived_to_T( map[pid] ); // #2 } else { Derived * p; // #3 ar >> p; shared_ptr<T> tmp( p ); t = p; map[pid] = p; } } } The line marked #1 is a general problem with the library, there is no way to associate user data with an archive, and some types require it. The lines marked #2 and #3 come into play when the actual pointer that was serialized was shared_ptr<T> t( new Derived ); #3 is not doable without help from the library, because - if I understand correctly - only the library knows how the type of a polymorphic object is stored in the archive. IOW the external representation is opaque, an "implementation detail". #2 is a problem because map[pid] was read in a previous call to load by #3 and points to some type that is not necessarily T.
Attempts to resolve this all ended up re-implementing some aspect of the serialization library.
Indeed.
I didn't really consider modifying the library to expose the relevant aspects IT'S implementation. That would entail much more than changing a private to public or adding a friend.
Maybe, but perhaps this would help others that are faced with a similar problem?
As far as I was concerned - implementing the the library once was enough. The implementation I made is straight forward and is compatible with all aspects of the serialization library including exported pointers, pointers to polymorphic base classes, non-default and private constructors - everything.
So maybe we can consider a practical compromise.
a) Grant me access to the internals of shared_ptr for now
a) You aren't going to get access to the internals of std::tr1::shared_ptr. b) Your implementation doesn't work when a weak_ptr is read before the corresponding shared_ptr. c) I "reserve the right to" change the implementation of boost::shared_ptr. IIUC with this implementation this will break every data file that contains a boost::shared_ptr. Correct?