diff -Naur ../boost_1_43_0-orig/boost/archive/detail/archive_cast.hpp ./boost/archive/detail/archive_cast.hpp --- ../boost_1_43_0-orig/boost/archive/detail/archive_cast.hpp 1969-12-31 19:00:00.000000000 -0500 +++ ./boost/archive/detail/archive_cast.hpp 2010-05-11 17:38:37.000000000 -0400 @@ -0,0 +1,113 @@ +#ifndef BOOST_ARCHIVE_DETAIL_ARCHIVE_CAST_HPP +#define BOOST_ARCHIVE_DETAIL_ARCHIVE_CAST_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// archive_cast.hpp + +// (C) Copyright 2007 Kim Barrett - kab@irobot.com +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +#include // must be the last header + +// helper for [i,o]serializers, allowing them to route operation to the +// appropriate specialized archive class. the purpose of archive_cast is to +// provide the serializer with a means of converting a reference to the +// basic_[i,o]archive to the appropriate archive class for further +// serialization. +// +// the Archive type must be the same type for all serialization calls +// applied to a given archive. if the archive is non-polymorphic, the Archive +// type must always be the most derived type of the archive. if the archive +// is polymorphic, the Archive type should always be the polymorphic archive +// type, else there would be little point in using a polymorphic archive type. +// +// in the non-polymorphic case, because Archive is the most derived archive +// type, which is (indirectly) derived from the basic archive class, the +// operation is a (supposedly safe) downcast. +// +// in the polymorphic case, Archive is the polymorphic archive class (or +// possibly something derived from it), and the obvious conversion is a +// dynamic_cast. however, in this case that dynamic_cast is a cross-cast, +// because the polymorphic archive class and the basic archive class are not +// in a base and derived relationship (in either order). cross-casts may be +// extremely expensive on some platforms, so a different approach is desired. +// +// archive_caster provides deferrable conversion of a basic_[i,o]archive to +// Archive. the cast function returns the result of that conversion as a +// void*. the conversion to void* permits the value to be stored in a location +// that has no information about Archive, with a later static cast from that +// void* to Archive*. +// +// archive_cast_pointer provides the customization point for the +// basic_[i,o]archive classes. the intended implementation is to cache the +// result of the caster in the basic archive on the first call, and use the +// previously cached result thereafter. +// +// archive_cast_impl provides a level of indirection so that archive_cast +// only instantiates the archive_caster template when actually needed, and +// not in the case where Archive is derived from From. + +namespace boost { +namespace archive { +namespace detail { + +template +struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_caster { + // out of line implementation in impl/archive_cast.ipp. + static void* cast(From& ar); +}; + +template +struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_cast_pointer { + // out of line implementations for each relevant From class + static void* get(From& ar, void* (*caster)(From& ar)); +}; + +template +struct BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_cast_impl; + +template +struct archive_cast_impl { // Archive derived from From + template + static Archive& cast(From& ar) { + return boost::serialization::smart_cast_reference(ar); + } +}; + +template +struct archive_cast_impl { // Archive not derived from From + template + static Archive& cast(From& ar) { + return *static_cast( + archive_cast_pointer::get( + ar, + archive_caster::cast)); + } +}; + +template +inline Archive& archive_cast(From& ar) { + // select implementation based on whether Archive is derived from From + return archive_cast_impl< + From, + boost::is_base_and_derived::value + >::template cast(ar); +} + +} // namespace detail +} // namespace archive +} // namespace boost + +#include // pops abi_prefix.hpp pragmas + +#endif // include guard diff -Naur ../boost_1_43_0-orig/boost/archive/detail/basic_iarchive.hpp ./boost/archive/detail/basic_iarchive.hpp --- ../boost_1_43_0-orig/boost/archive/detail/basic_iarchive.hpp 2009-12-14 18:52:51.000000000 -0500 +++ ./boost/archive/detail/basic_iarchive.hpp 2010-05-11 17:38:37.000000000 -0400 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include // must be the last header @@ -44,6 +45,7 @@ class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive : private boost::noncopyable { + friend class archive_cast_pointer; friend class basic_iarchive_impl; // hide implementation of this class to minimize header conclusion // in client code. I couldn't used scoped pointer with borland diff -Naur ../boost_1_43_0-orig/boost/archive/detail/basic_oarchive.hpp ./boost/archive/detail/basic_oarchive.hpp --- ../boost_1_43_0-orig/boost/archive/detail/basic_oarchive.hpp 2009-12-05 01:32:01.000000000 -0500 +++ ./boost/archive/detail/basic_oarchive.hpp 2010-05-11 17:38:37.000000000 -0400 @@ -26,6 +26,7 @@ // #include #include +#include #include #include // must be the last header @@ -46,6 +47,7 @@ class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive : private boost::noncopyable { + friend class archive_cast_pointer; friend class basic_oarchive_impl; // hide implementation of this class to minimize header conclusion // in client code. note: borland can't use scoped_ptr diff -Naur ../boost_1_43_0-orig/boost/archive/detail/iserializer.hpp ./boost/archive/detail/iserializer.hpp --- ../boost_1_43_0-orig/boost/archive/detail/iserializer.hpp 2010-02-26 00:08:08.000000000 -0500 +++ ./boost/archive/detail/iserializer.hpp 2010-05-11 17:38:37.000000000 -0400 @@ -85,6 +85,7 @@ // the following is need only for dynamic cast of polymorphic pointers #include #include +#include #include #include #include @@ -180,7 +181,7 @@ // make sure call is routed through the higest interface that might // be specialized by the user. boost::serialization::serialize_adl( - boost::serialization::smart_cast_reference(ar), + archive_cast(ar), * static_cast(x), file_version ); @@ -293,8 +294,7 @@ const unsigned int file_version ) const { - Archive & ar_impl = - boost::serialization::smart_cast_reference(ar); + Archive & ar_impl = archive_cast(ar); auto_ptr_with_deleter ap(heap_allocator::invoke()); if(NULL == ap.get()) diff -Naur ../boost_1_43_0-orig/boost/archive/detail/oserializer.hpp ./boost/archive/detail/oserializer.hpp --- ../boost_1_43_0-orig/boost/archive/detail/oserializer.hpp 2010-02-26 00:08:08.000000000 -0500 +++ ./boost/archive/detail/oserializer.hpp 2010-05-11 17:38:37.000000000 -0400 @@ -61,6 +61,7 @@ #include #include +#include #include #include #include @@ -146,7 +147,7 @@ // be specialized by the user. BOOST_STATIC_ASSERT(boost::is_const::value == false); boost::serialization::serialize_adl( - boost::serialization::smart_cast_reference(ar), + archive_cast(ar), * static_cast(const_cast(x)), version() ); @@ -191,8 +192,7 @@ // be specialized by the user. T * t = static_cast(const_cast(x)); const unsigned int file_version = boost::serialization::version::value; - Archive & ar_impl - = boost::serialization::smart_cast_reference(ar); + Archive & ar_impl = archive_cast(ar); boost::serialization::save_construct_data_adl( ar_impl, t, diff -Naur ../boost_1_43_0-orig/boost/archive/impl/archive_cast.ipp ./boost/archive/impl/archive_cast.ipp --- ../boost_1_43_0-orig/boost/archive/impl/archive_cast.ipp 1969-12-31 19:00:00.000000000 -0500 +++ ./boost/archive/impl/archive_cast.ipp 2010-05-11 17:38:37.000000000 -0400 @@ -0,0 +1,23 @@ +// archive_cast.ipp + +// (C) Copyright 2007 Kim Barrett - kab@irobot.com +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include // msvc 6.0 needs this for warning suppression + +#include + +namespace boost { +namespace archive { +namespace detail { + +template +void* archive_caster::cast(From& ar) { + return & dynamic_cast(ar); +} + +} // namespace detail +} // namespace archive +} // namespace boost diff -Naur ../boost_1_43_0-orig/libs/serialization/src/basic_iarchive.cpp ./libs/serialization/src/basic_iarchive.cpp --- ../boost_1_43_0-orig/libs/serialization/src/basic_iarchive.cpp 2010-03-11 11:43:40.000000000 -0500 +++ ./libs/serialization/src/basic_iarchive.cpp 2010-05-11 17:38:37.000000000 -0400 @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -49,8 +50,11 @@ class basic_iarchive_impl { friend class basic_iarchive; + friend class archive_cast_pointer; version_type m_archive_library_version; unsigned int m_flags; + void* (*m_cached_archive_caster)(basic_iarchive&); + void* m_cached_archive_cast_pointer; ////////////////////////////////////////////////////////////////////// // information about each serialized object loaded @@ -164,6 +168,8 @@ basic_iarchive_impl(unsigned int flags) : m_archive_library_version(BOOST_ARCHIVE_VERSION()), m_flags(flags), + m_cached_archive_caster(NULL), + m_cached_archive_cast_pointer(NULL), moveable_objects_start(0), moveable_objects_end(0), moveable_objects_recent(0), @@ -581,6 +587,31 @@ return pimpl->m_flags; } +// this is identical to the corresponding basic_oarchive function. +// it would be nice if they could be merged into one parameterized definition, +// but doing so seems more work than accepting and noting the duplication. +template<> +BOOST_ARCHIVE_DECL(void*) +archive_cast_pointer::get( + basic_iarchive& ar, void* (*caster)(basic_iarchive&)) +{ + void* result = ar.pimpl->m_cached_archive_cast_pointer; + if (result) { + // already cached. + // if debug build, verify called with same caster. + assert(caster == ar.pimpl->m_cached_archive_caster); + // if debug build, verify cached result matches caster result. + // otherwise, assume it does and skip expensive cast + assert(result == caster(ar)); + } else { + // on first call, use the caster's result and cache for later reuse. + result = caster(ar); + ar.pimpl->m_cached_archive_caster = caster; + ar.pimpl->m_cached_archive_cast_pointer = result; + } + return result; +} + } // namespace detail } // namespace archive } // namespace boost diff -Naur ../boost_1_43_0-orig/libs/serialization/src/basic_oarchive.cpp ./libs/serialization/src/basic_oarchive.cpp --- ../boost_1_43_0-orig/libs/serialization/src/basic_oarchive.cpp 2010-03-11 11:43:40.000000000 -0500 +++ ./libs/serialization/src/basic_oarchive.cpp 2010-05-11 17:46:14.000000000 -0400 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -44,7 +45,10 @@ class basic_oarchive_impl { friend class basic_oarchive; + friend class archive_cast_pointer; unsigned int m_flags; + void* (*m_cached_archive_caster)(basic_oarchive&); + void* m_cached_archive_cast_pointer; ////////////////////////////////////////////////////////////////////// // information about each serialized object saved @@ -139,6 +143,8 @@ basic_oarchive_impl(unsigned int flags) : m_flags(flags), + m_cached_archive_caster(NULL), + m_cached_archive_cast_pointer(NULL), pending_object(NULL), pending_bos(NULL) {} @@ -460,6 +466,31 @@ basic_oarchive::end_preamble(){ } +// this is identical to the corresponding basic_iarchive function. +// it would be nice if they could be merged into one parameterized definition, +// but doing so seems more work than accepting and noting the duplication. +template<> +BOOST_ARCHIVE_DECL(void*) +archive_cast_pointer::get( + basic_oarchive& ar, void* (*caster)(basic_oarchive&)) +{ + void* result = ar.pimpl->m_cached_archive_cast_pointer; + if (result) { + // already cached. + // if debug build, verify called with same caster. + assert(caster == ar.pimpl->m_cached_archive_caster); + // if debug build, verify cached result matches caster result. + // otherwise, assume it does and skip expensive cast + assert(result == caster(ar)); + } else { + // on first call, use the caster's result and cache for later reuse. + result = caster(ar); + ar.pimpl->m_cached_archive_caster = caster; + ar.pimpl->m_cached_archive_cast_pointer = result; + } + return result; +} + } // namespace detail } // namespace archive } // namespace boost diff -Naur ../boost_1_43_0-orig/libs/serialization/src/polymorphic_iarchive.cpp ./libs/serialization/src/polymorphic_iarchive.cpp --- ../boost_1_43_0-orig/libs/serialization/src/polymorphic_iarchive.cpp 2009-08-01 19:32:25.000000000 -0400 +++ ./libs/serialization/src/polymorphic_iarchive.cpp 2010-05-11 17:38:37.000000000 -0400 @@ -18,11 +18,15 @@ #include #include +#include +#include + namespace boost { namespace archive { namespace detail { template class archive_serializer_map; +template class archive_caster; } // detail } // archive diff -Naur ../boost_1_43_0-orig/libs/serialization/src/polymorphic_oarchive.cpp ./libs/serialization/src/polymorphic_oarchive.cpp --- ../boost_1_43_0-orig/libs/serialization/src/polymorphic_oarchive.cpp 2009-09-19 22:18:02.000000000 -0400 +++ ./libs/serialization/src/polymorphic_oarchive.cpp 2010-05-11 17:38:37.000000000 -0400 @@ -18,11 +18,15 @@ #include #include +#include +#include + namespace boost { namespace archive { namespace detail { template class archive_serializer_map; +template class archive_caster; } // detail } // archive