$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r55675 - trunk/boost/serialization
From: ramey_at_[hidden]
Date: 2009-08-20 01:32:15
Author: ramey
Date: 2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
New Revision: 55675
URL: http://svn.boost.org/trac/boost/changeset/55675
Log:
Fix error in export functionality:
a) set key when etf record is constructed.
b) make corrections in no_rtti type system
c) make no_rtti type system more robust and self-diagnosing
Text files modified: 
   trunk/boost/serialization/export.hpp                     |    95 +++++++++++++++++++++------------------ 
   trunk/boost/serialization/extended_type_info.hpp         |    37 +++++++++++---                          
   trunk/boost/serialization/extended_type_info_no_rtti.hpp |    48 +++++++++++++++++--                     
   trunk/boost/serialization/extended_type_info_typeid.hpp  |    23 ++++++---                               
   trunk/boost/serialization/version.hpp                    |    25 ++++++----                              
   5 files changed, 152 insertions(+), 76 deletions(-)
Modified: trunk/boost/serialization/export.hpp
==============================================================================
--- trunk/boost/serialization/export.hpp	(original)
+++ trunk/boost/serialization/export.hpp	2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
@@ -29,14 +29,11 @@
 #include <boost/preprocessor/stringize.hpp>
 #include <boost/type_traits/is_polymorphic.hpp>
 
-#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO   
-    #include <boost/serialization/extended_type_info_typeid.hpp>   
-#endif 
 #include <boost/serialization/static_warning.hpp>
-#include <boost/serialization/type_info_implementation.hpp>
 #include <boost/serialization/assume_abstract.hpp>
 #include <boost/serialization/force_include.hpp>
 #include <boost/serialization/singleton.hpp>
+#include <boost/serialization/non_convertible.hpp>
 
 #include <boost/archive/detail/register_archive.hpp>
 #include <boost/mpl/assert.hpp>
@@ -118,60 +115,72 @@
     );
 }
 
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
 namespace {
 
 template<class T>
 struct guid_initializer
 {  
-    const guid_initializer & export_guid(char const* /* key */, mpl::false_){
+    void export_guid(boost::mpl::false_){
         // generates the statically-initialized objects whose constructors
         // register the information allowing serialization of T objects
         // through pointers to their base classes.
-        instantiate_ptr_serialization((T*)0, 0, adl_tag());
-        return *this;
+        boost::archive::detail::instantiate_ptr_serialization(
+            (T*)0, 
+            0, 
+            boost::archive::detail::adl_tag()
+        );
     }
-    const guid_initializer & export_guid(char const* /*key*/, mpl::true_){
-        return *this;
-    }
-    const guid_initializer & export_guid(char const* key){
+    void export_guid(boost::mpl::true_){}
+    guid_initializer(){
         BOOST_STATIC_WARNING(boost::is_polymorphic<T>::value);
-        assert(NULL != key);
-        boost::serialization::singleton<
-            BOOST_DEDUCED_TYPENAME 
-            boost::serialization::type_info_implementation<T>::type
-        >::get_mutable_instance().key_register(key);
         // note: exporting an abstract base class will have no effect
         // and cannot be used to instantitiate serialization code
         // (one might be using this in a DLL to instantiate code)
         //BOOST_STATIC_WARNING(! boost::serialization::is_abstract<T>::value);
-        return export_guid(key, boost::serialization::is_abstract<T>());
+        export_guid(boost::serialization::is_abstract<T>());
     }
 };
 
-template<typename T>
-struct init_guid;
+template<class T>
+struct init_guid {
+    static guid_initializer< T > const & g;
+};
 
 } // anonymous
-} // namespace detail
-} // namespace archive
-} // namespace boost
 
-#define BOOST_CLASS_EXPORT_GUID(T, K)                                  \
-    namespace boost {                                                  \
-    namespace archive {                                                \
-    namespace detail {                                                 \
+#define BOOST_CLASS_EXPORT_IMPLEMENT(T)                                \
     namespace {                                                        \
-    template<>                                                         \
-    struct init_guid< T > {                                            \
-        static ::boost::archive::detail::guid_initializer< T > const   \
-            & guid_initializer;                                        \
-    };                                                                 \
-    ::boost::archive::detail::guid_initializer< T > const &            \
-        ::boost::archive::detail::init_guid< T >::guid_initializer =   \
+        template <> guid_initializer< T > const & init_guid< T >::g =  \
            ::boost::serialization::singleton<                          \
-               ::boost::archive::detail::guid_initializer< T >         \
-           >::get_mutable_instance().export_guid(K);                   \
-    }}}}                                                                \
+               guid_initializer< T >                                   \
+           >::get_mutable_instance();                                  \
+    }                                                                  \
+/**/
+
+#define BOOST_CLASS_EXPORT_KEY2(T, K)          \
+namespace boost {                              \
+namespace serialization {                      \
+template<>                                     \
+struct guid_defined<T> : boost::mpl::true_ {}; \
+template<>                                     \
+inline const char * guid<T>(){                 \
+    return K;                                  \
+}                                              \
+} /* serialization */                          \
+} /* boost */                                  \
+/**/
+
+#define BOOST_CLASS_EXPORT_KEY(T)                                      \
+    BOOST_CLASS_EXPORT_KEY2(T, BOOST_PP_STRINGIZE(T))                                                                  \
+/**/
+
+#define BOOST_CLASS_EXPORT_GUID(T, K)                                  \
+BOOST_CLASS_EXPORT_KEY2(T, K)                                          \
+BOOST_CLASS_EXPORT_IMPLEMENT(T)                                        \
 /**/
 
 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
@@ -181,13 +190,13 @@
 // compiler we ask users to specifically register base/derived class
 // relationships for exported classes.  On all other compilers, use of
 // this macro is entirely optional.
-# define BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(Base,Derived)                  \
-namespace {                                                                         \
-  static int BOOST_PP_CAT(boost_serialization_mwerks_init_, __LINE__) =             \
-  (::boost::archive::detail::instantiate_ptr_serialization((Derived*)0,0), 3);      \
-  static int BOOST_PP_CAT(boost_serialization_mwerks_init2_, __LINE__) = (          \
-      ::boost::serialization::void_cast_register((Derived*)0,(Base*)0)              \
-    , 3);                                                                           \
+# define BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(Base,Derived)             \
+namespace {                                                                    \
+  static int BOOST_PP_CAT(boost_serialization_mwerks_init_, __LINE__) =        \
+  (::boost::archive::detail::instantiate_ptr_serialization((Derived*)0,0), 3); \
+  static int BOOST_PP_CAT(boost_serialization_mwerks_init2_, __LINE__) = (     \
+      ::boost::serialization::void_cast_register((Derived*)0,(Base*)0)         \
+    , 3);                                                                      \
 }
 
 #else
Modified: trunk/boost/serialization/extended_type_info.hpp
==============================================================================
--- trunk/boost/serialization/extended_type_info.hpp	(original)
+++ trunk/boost/serialization/extended_type_info.hpp	2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
@@ -26,6 +26,7 @@
 #include <boost/serialization/config.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/weak_ptr.hpp>
+#include <boost/mpl/bool.hpp>
 
 #include <boost/config/abi_prefix.hpp> // must be the last header
 #ifdef BOOST_MSVC
@@ -35,13 +36,24 @@
 
 #define BOOST_SERIALIZATION_MAX_KEY_SIZE 128
 
+
 namespace boost { 
 namespace serialization {
+
+namespace void_cast_detail{
+    class void_caster;
+}
+
 class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) extended_type_info :
     private boost::noncopyable
 {
-private: 
+private:
+    friend class boost::serialization::void_cast_detail::void_caster;
     boost::shared_ptr<const extended_type_info> m_this;
+    boost::weak_ptr<const extended_type_info>
+    get_weak_ptr() const {
+        return m_this;
+    }
 
     // used to uniquely identify the type of class derived from this one
     // so that different derivations of this class can be simultaneously
@@ -49,13 +61,18 @@
     const unsigned int m_type_info_key;
     virtual bool is_less_than(const extended_type_info & /*rhs*/) const = 0;
     virtual bool is_equal(const extended_type_info & /*rhs*/) const = 0;
-    void key_unregister();
-protected:
     const char * m_key;
+
+protected:
+    void key_unregister() const;
+    void key_register() const;
     // this class can't be used as is. It's just the 
     // common functionality for all type_info replacement
     // systems.  Hence, make these protected
-    extended_type_info(const unsigned int type_info_key = 0);
+    extended_type_info(
+    	const unsigned int type_info_key,
+    	const char * key
+    );
     // account for bogus gcc warning
     #if defined(__GNUC__)
     virtual
@@ -65,16 +82,11 @@
     const char * get_key() const {
         return m_key;
     }
-    void key_register(const char *key);
     bool operator<(const extended_type_info &rhs) const;
     bool operator==(const extended_type_info &rhs) const;
     bool operator!=(const extended_type_info &rhs) const {
         return !(operator==(rhs));
     }
-    boost::weak_ptr<const extended_type_info>
-    get_weak_ptr() const {
-        return m_this;
-    }
     static const extended_type_info * find(const char *key);
     // for plugins
     virtual void * construct(unsigned int /*count*/ = 0, ...) const {
@@ -86,6 +98,13 @@
     }
 };
 
+template<class T>
+struct guid_defined : boost::mpl::false_ {};
+template<class T>
+inline const char * guid(){
+    return NULL;
+}
+
 } // namespace serialization 
 } // namespace boost
 
Modified: trunk/boost/serialization/extended_type_info_no_rtti.hpp
==============================================================================
--- trunk/boost/serialization/extended_type_info_no_rtti.hpp	(original)
+++ trunk/boost/serialization/extended_type_info_no_rtti.hpp	2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
@@ -25,6 +25,9 @@
 #include <boost/serialization/singleton.hpp>
 #include <boost/serialization/extended_type_info.hpp>
 #include <boost/serialization/factory.hpp>
+#include <boost/serialization/throw_exception.hpp>
+
+#include <boost/mpl/if.hpp>
 
 #include <boost/config/abi_prefix.hpp> // must be the last header
 #ifdef BOOST_MSVC
@@ -38,7 +41,7 @@
 // define a special type_info that doesn't depend on rtti which is not
 // available in all situations.
 
-namespace detail {
+namespace no_rtti_system {
 
 // common base class to share type_info_key.  This is used to 
 // identify the method used to keep track of the extended type
@@ -46,7 +49,7 @@
     public extended_type_info
 {
 protected:
-    extended_type_info_no_rtti_0();
+    extended_type_info_no_rtti_0(const char * key);
     ~extended_type_info_no_rtti_0();
 public:
     virtual bool
@@ -55,17 +58,47 @@
     is_equal(const boost::serialization::extended_type_info &rhs) const ;
 };
 
-} // detail
+} // no_rtti_system
 
 template<class T>
 class extended_type_info_no_rtti : 
-    public detail::extended_type_info_no_rtti_0,
+    public no_rtti_system::extended_type_info_no_rtti_0,
     public singleton<extended_type_info_no_rtti<T> >
 {
+    template<bool tf>
+    struct action {
+        struct defined {
+            static const char * invoke(){
+                return guid<T>();
+            }
+        };
+        struct undefined {
+            // if your program traps here - you failed to 
+            // export a guid for this type.  the no_rtti
+            // system requires export for types serialized
+            // as pointers.
+            BOOST_STATIC_ASSERT(0 == sizeof(T));
+            static const char * invoke();
+        };
+        static const char * invoke(){
+            typedef 
+                BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
+                    tf,
+                    defined,
+                    undefined
+                >::type type;
+            return type::invoke();
+        }
+    };
 public:
     extended_type_info_no_rtti() :
-        detail::extended_type_info_no_rtti_0()
-    {}
+        no_rtti_system::extended_type_info_no_rtti_0(get_key())
+    {
+        key_register();
+    }
+    ~extended_type_info_no_rtti(){
+        key_unregister();
+    }
     const extended_type_info *
     get_derived_extended_type_info(const T & t) const {
         // find the type that corresponds to the most derived type.
@@ -77,6 +110,9 @@
         assert(NULL != derived_key);
         return boost::serialization::extended_type_info::find(derived_key);
     }
+    const char * get_key() const{
+        return action<guid_defined<T>::value >::invoke();
+    }
     void * construct(unsigned int count, ...) const{
         // count up the arguments
         std::va_list ap;
Modified: trunk/boost/serialization/extended_type_info_typeid.hpp
==============================================================================
--- trunk/boost/serialization/extended_type_info_typeid.hpp	(original)
+++ trunk/boost/serialization/extended_type_info_typeid.hpp	2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
@@ -32,6 +32,8 @@
 #include <boost/serialization/extended_type_info.hpp>
 #include <boost/serialization/factory.hpp>
 
+#include <boost/mpl/if.hpp>
+
 #include <boost/config/abi_prefix.hpp> // must be the last header
 #ifdef BOOST_MSVC
 #  pragma warning(push)
@@ -40,14 +42,14 @@
 
 namespace boost {
 namespace serialization {
-namespace detail {
+namespace typeid_system {
 
 class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) extended_type_info_typeid_0 : 
     public extended_type_info
 {
 protected:
     const std::type_info * m_ti;
-    extended_type_info_typeid_0();
+    extended_type_info_typeid_0(const char * key);
     ~extended_type_info_typeid_0();
     void type_register(const std::type_info & ti);
     void type_unregister();
@@ -63,20 +65,22 @@
     }
 };
 
-} // namespace detail
+} // typeid_system
 
 template<class T>
 class extended_type_info_typeid : 
-    public detail::extended_type_info_typeid_0,
+    public typeid_system::extended_type_info_typeid_0,
     public singleton<extended_type_info_typeid<T> >
 {
 public:
     extended_type_info_typeid() :
-        detail::extended_type_info_typeid_0()
+        typeid_system::extended_type_info_typeid_0(get_key())
     {
         type_register(typeid(T));
+        key_register();
     }
     ~extended_type_info_typeid(){
+        key_unregister();
         type_unregister();
     }
     // get the eti record for the true type of this record
@@ -87,11 +91,14 @@
         // only does something if the class has at least one virtual function.
         BOOST_STATIC_WARNING(boost::is_polymorphic<T>::value);
         return 
-            detail::extended_type_info_typeid_0::get_extended_type_info(
+            typeid_system::extended_type_info_typeid_0::get_extended_type_info(
                 typeid(t)
             );
     }
-    void * construct(unsigned int count, ...) const{
+    const char * get_key() const {
+        return boost::serialization::guid<T>();
+    }
+    virtual void * construct(unsigned int count, ...) const{
         // count up the arguments
         std::va_list ap;
         va_start(ap, count);
@@ -112,7 +119,7 @@
             return NULL;
         }
     }
-    void destroy(void const * const /* p */) const {
+    virtual void destroy(void const * const /* p */) const {
         // the only current usage of extended type info is in the
         // serialization library.  The statement below requires
         // that destructor of type T be public and this creates
Modified: trunk/boost/serialization/version.hpp
==============================================================================
--- trunk/boost/serialization/version.hpp	(original)
+++ trunk/boost/serialization/version.hpp	2009-08-20 01:32:13 EDT (Thu, 20 Aug 2009)
@@ -55,6 +55,18 @@
 } // namespace serialization
 } // namespace boost
 
+/* note: at first it seemed that this would be a good place to trap
+ * as an error an attempt to set a version # for a class which doesn't
+ * save its class information (including version #) in the archive.
+ * However, this imposes a requirement that the version be set after
+ * the implemention level which would be pretty confusing.  If this
+ * is to be done, do this check in the input or output operators when
+ * ALL the serialization traits are available.  Included the implementation
+ * here with this comment as a reminder not to do this!
+ */
+//#include <boost/serialization/level.hpp>
+//#include <boost/mpl/equal_to.hpp>
+
 // specify the current version number for the class
 #define BOOST_CLASS_VERSION(T, N)                                      \
 namespace boost {                                                      \
@@ -65,18 +77,11 @@
     typedef mpl::int_<N> type;                                         \
     typedef mpl::integral_c_tag tag;                                   \
     BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value); \
-    /* require that class info saved when versioning is used */        \
     /*                                                                 \
     BOOST_STATIC_ASSERT((                                              \
-        mpl::or_<                                                      \
-            mpl::equal_to<                                             \
-                mpl::int_<0>,                                          \
-                mpl::int_<N>                                           \
-            >,                                                         \
-            mpl::equal_to<                                             \
-                implementation_level<T>,                               \
-                mpl::int_<object_class_info>                           \
-            >                                                          \
+        mpl::equal_to<                                                 \
+            :implementation_level<T >,                                 \
+            mpl::int_<object_class_info>                               \
         >::value                                                       \
     ));                                                                \
     */                                                                 \