On 11/11/05 4:40 PM, "Robert Ramey"
David Abrahams wrote:
"Robert Ramey"
writes: OK, let me rephrase that. There would be no advantage to doing that since one could ->
make thier own derivation(s) of one or more archive classes or even a whole new archive class - but that doesn't represent any conflict with the current library.
A special archive class doesn't help if the interface for serializing arrays isn't a standard part of the archive concept. Everyone who writes a datatype containing an array will need to use that interface in his serialize function.
The archive class concept indicates that the following expression is true
ar << t
for any serializable type t.
The documentation defines a serializable type as:
A type T is Serializable if and only if one of the following is true: a.. it is a primitive type. In this document, we use the term primitive type to mean types whose data is simply saved/loaded to/from an archive with no further processing. Arithmetic (including characters), bool, enum and stl::string and stl::wstring types are primitive types. Using serialization traits, any user type can also be designated as "primitive" so that it is handled in this way. b.. It is a class type and for all Archive classes, one of the following has been declared: a.. a class member function serialize b.. a global function serialize c.. it is a pointer to a Serializable type. d.. it is a reference to a Serializable type. e.. it is an native C++ Array of Serializable type. That is any array is serializable if its elements are serializable. Doesn't that cover it?
I take it that member pointers (both data and function) cannot be serialized, right? I guess I would map each qualifying member to a number (or string if open-ended) and serialize that number. I think we need two new archive loading primitives. 1. Array segment. You already have compile-time arrays covered, but I don't see anything about run-time arrays. (Surprising considering how often CT-arrays are "dissed" for RT-arrays.) A run-time array is defined by a pointer to the first element and an element count: // I'm just guessing what your base type looks like class archive_base { //... template < typename T > status_type archive_rtarray( T *a, size_t &c ) { this->archive( c ); for ( size_t i = c ; i ; --i, ++a ) this->archive( *a ); return OK; } //... }; Any class that maintains its own array of elements that doesn't use a smart container, standard or otherwise, would need this for serialization. And what if a class uses a non-standard container? We could use an iterator-based routine: class archive_base { //... template < typename T > status_type archive_container_save( T const &c ) { typedef typename T::const_iterator iterator; iterator const e = c.end(); for ( iterator b = c.begin() ; e != b ; ++b ) this->archive_save( *b ); // You would proably use something kewl // from Boost.bind/lambda here instead. return OK; } template < typename T > status_type archive_container_load( T &c ) { typedef typename T::size_type size_type; size_type s; this->archive_load( s ); typename T::element_type temp; for ( size_type i = 0 ; i < s ; ++i ) { this->archive_load( temp ); c.push_back( temp ); } return OK; } //... } The routines for the standard containers could call these primitives. The one for std::vector could use the RT-array primitive. Finally, a fast archive could be keyed to a type's POD status. (I think we have a type-trait for that.) We would make a subclass of the binary archive class that has overrides for POD types. Those types would dump their bytes directly, even if they're arrays or structures. Obviously we give up portability for speed. My new RT-array primitive should also be optimized for POD types. Non-PODs would call their regular coding function, hopefully getting a speed-up from the individual component speed-ups. -- Daryle Walker Mac, Internet, and Video Game Junkie darylew AT hotmail DOT com