
I've also been thinking about this. My very first attempt a long time ago was something like: 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. } Adding a map in the archive instance to permit shared_ptrs to be "matched up" would seem to me to solve the problem. So a custom archive which includeded such a map would be all that was needed I believe. My main objection to this is coupling the archives to specific data types. I haven't seen a way to do this in a generic way so that it could handle the "next" shared_ptr.
I looked at the implementation of the serialization library. Quite complicated and remarkable in its own way. ;-)
I'll choose to take that as a complement.
The root cause is, in my opinion, that you started off with something and then added features as requested.
Had you started with the _requested features_ you might not have needed to add the rest. Anyway, to get back to shared_ptr.
Actually I started with the features I felt were missing in all the other libraries I looked at. Then there were the requested features. They all fit in a more or less natural spot. There is no feature in there that someone has not considered really, really indispensible. There is only one feature that I don't think has been used - that is the extended type info which doesn't rely on std::type_info. I do get regular feed back. The draft package on my personal website has been downloaded 3000 times. I don't know how many times it was downloaded from the yahoo file section. Every couple of weeks I get feedback from someone congratulating me on getting it into boost - and giving me an explanation of how their own system works. I also get a lot of short explanations on how simple it would be to ... In incredible amount of time is spent addressing the vagarities of different C++ implementations. I don't believe that anyone who hasn't done something like this appreciates the amount of effort this aspect consumes.
4. The ability to deserialize a polymorphic object.
Initially I'll deserialize a raw pointer.
The problem with this approach is that the deserialized shared_ptr<T> will contain a deleter that will attempt to destroy a T, whereas the original may have had a deleter destroying a Derived.
This can affect users if ~T is inaccessible or non-virtual or if T is incomplete.
It is not possible to solve this without help from the library; basically, the T* deserializer (which internally operates with void*/type_info pairs) will need to be duplicated to return shared_ptr<T> (internally shared_ptr<void>/type_info).
That's quite a mouthful - I'll have to think about that.
5. The ability to downcast the deserialized shared_ptr<T> to shared_ptr<void> pointing to the most derived object.
This can be done with dynamic_pointer_cast<void>.
The external representation of shared_ptr / weak_ptr is as demonstrated by the earlier example:
- int pid; - (opt) T * px;
where pid == 0 denotes an empty pointer, a newly seen pid denotes a new object and is followed by px, and an already seen pid denotes a reference to an existing object.
shared_ptr probably needs to be marked as "never track, unversioned" to not clutter the archive, but I'm not sure what is the official serialization library policy regarding std:: types.
I would have to think about that as well. I'm not convinced that you couldn't just cast to void * and use that to lookup in the map. I think marking it unversioned would be a mistake as this won't be trivial in any case. Marking never track is probably a good idea - though in practice, the default is that things are tracked only if used as pointers. I doubt anyone will want to serialize a shared_ptr through a raw pointer. (LOL - I'm being presumptuious again - I can't help myself) Robert Ramey