On Mon, Sep 21, 2009 at 21:25, Robert Ramey
Stefan Strasser wrote:
Am Monday 21 September 2009 20:27:59 schrieb Robert Ramey:
Stefan Strasser wrote:
I think to support this an other use cases like it common_archive would have to be moved outside of the linked library into a header and be made more generic.
common_archive is a template - it's not in the linked library.
ok, I must have mixed up some types. the point was that the ultimate base class, that handles the type registration and object tracking etc., is linked .cpp and not very configurable. the optimum case imho would be that you could pass a traits class to that archive base class, that gets called whenever there is an object or type to be registered and is queried for existing objects and types later on. that way you could disable registration, save type registration outside of the archive itself, let type registration span multiple archives etc, make sure type registration doesn't allocate etc.
as I alluded to before - what I would like to know is why I derived trivial_archive from common_archive. I don't remember what made me do this. It seems that if this isn't done then save/load_object is necessary. So the question is - why is this? It is an oversight somewhere? or does the archive concept have to be changed.
Personally, I generally don't like the "traits class" as an argument. It sort of implies that that the template has a lot of "if -" code which navigates the traits. A "policy class" is better but can still make things complex. Personally I prefer composition of funtionality through inheritance. This can be seen in the class diagram for the serialization library. And your example makes me more convinced than ever that this is basically right. Now the only loose end it investigate why save/load object is required.
I found a lead to that. When the archive calls archive::save, a chain of 'invoke' calls is done to select the right serialization method for type T. When I pass std::vector<double> as T, it encounters a branch in oserializer.hpp:245, in struct 'save_conditional::invoke' . <code> // adds class information to the archive. This includes // serialization level and class version struct save_conditional { static void invoke(Archive &ar, const T &t){ //if(0 == (ar.get_flags() & no_tracking)) save_standard::invoke(ar, t); //else // save_only::invoke(ar, t); } }; </code> The alternative branch is commented out, but let that be the path that needs to be taken by my code. Current code calls save_standard, which calls directly ' ar.save_object'. save_object in turn depends on basic_oarchive to do its job. If save_only was taken, the 'non-basic_oarchive' serialization code path would have been taken. For some reason (I've spent an hour staring at it), my unit test did not discover this flaw in my code and does as if serialisation of the std::vector was fine. I'm overlooking something stupid clearly... Anyway, as it seems now, the code path taken by archive::save/load mandates derivation of basic_?archive. Maybe I should have called another 'selection' function ? like archive::save_only directly ? Peter