--- boost/serialization/export.hpp 2005-11-21 15:11:23.000000000 -0600 +++ boost/serialization/export.hpp 2007-03-20 13:13:04.319910745 -0500 @@ -29,6 +29,7 @@ // file declaration header #if ! defined(BOOST_ARCHIVE_BASIC_ARCHIVE_HPP) #define BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, K, ASEQ) +#define BOOST_CLASS_EXPORT_ALIAS_IMPL(T, K) #else #include @@ -158,11 +159,31 @@ template const guid_initializer guid_initializer::instance; +// instantiation of this template creates a static object. +template +struct alias_initializer { + typedef BOOST_DEDUCED_TYPENAME boost::serialization::type_info_implementation::type eti_type; + static void alias_register(const char *key){ + eti_type::alias_register(key); + } + static const alias_initializer instance; + alias_initializer(const char *key = 0) BOOST_USED ; +}; + +template +alias_initializer::alias_initializer(const char *key){ + if(0 != key) + alias_register(key); +} + +template +const alias_initializer alias_initializer::instance; + // only gcc seems to be able to explicitly instantiate a static instance. // but all can instantiate a function that refers to a static instance // the following optimization - inhibiting explicit instantiation for abstract -// classes breaks msvc compliles +// classes breaks msvc compiles template struct export_instance { struct abstract { @@ -243,6 +264,16 @@ } } } \ /**/ +#define BOOST_CLASS_EXPORT_ALIAS_IMPL(T, K) \ + namespace boost { \ + namespace archive { \ + namespace detail { \ + template<> \ + const alias_initializer< T > \ + alias_initializer< T >::instance(K); \ + } } } \ + /**/ + #endif // check for unnecessary export. T isn't polymorphic so there is no @@ -278,4 +309,16 @@ ) \ /**/ +// Defines an alias K that will be recognized as an alternative class name for +// type T when loading polymorphic classes from archives. Note that alias +// exports must happen after primary exports (BOOST_CLASS_EXPORT_GUID(), +// BOOST_CLASS_EXPORT(), etc.), and that the class name saved into +// out-archives will always be the primary name, not an alias. +#define BOOST_CLASS_EXPORT_ALIAS(T, K) \ + BOOST_CLASS_EXPORT_ALIAS_IMPL( \ + T, \ + K \ + ) \ + /**/ + #endif // BOOST_SERIALIZATION_EXPORT_HPP --- boost/serialization/extended_type_info.hpp 2005-11-23 11:27:20.000000000 -0600 +++ boost/serialization/extended_type_info.hpp 2007-03-20 11:36:06.140692450 -0500 @@ -45,10 +45,12 @@ // so that different derivations of this class can be simultaneously // included in implementation of sets and maps. const char * m_type_info_key; - // flag to indicate wheter its been registered by type; + // flag to indicate whether it's been registered by type; bool m_self_registered; - // flag to indicate wheter its been registered by type; + // flag to indicate whether it's been registered by type; bool m_key_registered; + // flag to indicate whether it's been registered by type; + bool m_alias_registered; // flag indicating that no virtual function should be called here // this is necessary since it seems that at least one compiler (borland // and one version of gcc call less_than above when erasing even @@ -65,6 +67,7 @@ public: void self_register(); void key_register(const char *key); + void alias_register(const char *key); bool is_destructing() const { return m_is_destructing; } --- boost/serialization/extended_type_info_no_rtti.hpp 2005-11-23 11:27:20.000000000 -0600 +++ boost/serialization/extended_type_info_no_rtti.hpp 2007-03-20 13:14:19.727431000 -0500 @@ -91,6 +91,12 @@ eti->key_register(key); // initialize key and add to table eti->self_register(); // add type to type table } + static void + alias_register(const char * key){ + boost::serialization::extended_type_info * eti; + eti = get_instance(); + eti->alias_register(key); // initialize key and add to table + } }; } // namespace detail --- boost/serialization/extended_type_info_typeid.hpp 2005-11-23 11:27:20.000000000 -0600 +++ boost/serialization/extended_type_info_typeid.hpp 2007-03-20 13:14:49.632826634 -0500 @@ -100,6 +100,10 @@ export_register(const char * key){ get_instance()->key_register(key); } + static void + alias_register(const char * key){ + get_instance()->alias_register(key); + } }; } // namespace detail --- libs/serialization/src/extended_type_info.cpp 2005-10-02 01:01:14.000000000 -0500 +++ libs/serialization/src/extended_type_info.cpp 2007-03-20 11:36:43.902458793 -0500 @@ -11,6 +11,7 @@ #include #include +#include #include #include // msvc needs this to suppress warning @@ -88,7 +89,7 @@ // note: the following can't be used as this function // is called from a destructor of extended_type_info. // This will generate an error on some machines - which - // makes sense be cause by this time the derived class data + // makes sense because by this time the derived class data // might be gone. Leave this in as a reminder not to do this #if 0 tkmap::type::iterator it; @@ -116,20 +117,20 @@ struct key_compare { bool - operator()(const extended_type_info * lhs, const extended_type_info * rhs) const + operator()(const char * lhs, const char * rhs) const { // shortcut to exploit string pooling - if(lhs->get_key() == rhs->get_key()) + if(lhs == rhs) return false; - if(NULL == lhs->get_key()) + if(NULL == lhs) return true; - if(NULL == rhs->get_key()) + if(NULL == rhs) return false; - return std::strcmp(lhs->get_key(), rhs->get_key()) < 0; + return std::strcmp(lhs, rhs) < 0; } }; // typedef std::multiset type; - typedef std::set type; + typedef std::map type; type m_map; static ktmap * m_self; ktmap(){} @@ -150,8 +151,7 @@ }; static ktmap::type::iterator lookup(const char *key){ - extended_type_info_arg arg(key); - return m_self->m_map.find(&arg); + return m_self->m_map.find(key); } public: @@ -159,26 +159,25 @@ m_self = NULL; } static void - insert(const extended_type_info * eti){ + insert(const char * key, const extended_type_info * eti){ if(NULL == m_self){ static ktmap instance; m_self = & instance; } // make sure that all GUIDs are unique - assert(lookup(eti->get_key()) == m_self->m_map.end()); - m_self->m_map.insert(eti); + assert(lookup(key) == m_self->m_map.end()); + m_self->m_map.insert(std::make_pair(key, eti)); } static const extended_type_info * find(const char *key) { if(NULL == m_self) return NULL; - extended_type_info_arg arg(key); ktmap::type::const_iterator it; - it = m_self->m_map.find(&arg); + it = m_self->m_map.find(key); if(it == m_self->m_map.end()) return NULL; - return *it; + return it->second; } static void purge(const extended_type_info * eti){ @@ -187,7 +186,7 @@ // note: the following can't be used as this function // is called from a destructor of extended_type_info. // This will generate an error on some machines - which - // makes sense be cause by this time the derived class data + // makes sense because by this time the derived class data // might be gone. Leave this in as a reminder not to do this #if 0 ktmap::type::iterator it; @@ -202,7 +201,7 @@ while(i != k){ // note that the erase might invalidate i so save it here ktmap::type::iterator j = i++; - if(*j == eti) + if(j->second == eti) m_self->m_map.erase(j); } } @@ -230,10 +229,18 @@ if(NULL == key_) return; m_key = key_; - detail::ktmap::insert(this); + detail::ktmap::insert(key_, this); m_key_registered = true; } +BOOST_SERIALIZATION_DECL(void) +extended_type_info::alias_register(const char *alias) { + if(NULL == alias) + return; + detail::ktmap::insert(alias, this); + m_alias_registered = true; +} + BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) extended_type_info::extended_type_info( const char * type_info_key @@ -241,6 +248,7 @@ m_type_info_key(type_info_key), m_self_registered(false), m_key_registered(false), + m_alias_registered(false), m_is_destructing(false) {} @@ -251,7 +259,7 @@ BOOST_TRY{ if(m_self_registered) detail::tkmap::purge(this); - if(m_key_registered) + if(m_key_registered || m_alias_registered) detail::ktmap::purge(this); unregister_void_casts(this); }