williamr@2: #ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP williamr@2: #define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP williamr@2: williamr@2: // MS compatible compilers support #pragma once williamr@2: #if defined(_MSC_VER) && (_MSC_VER >= 1020) williamr@2: # pragma once williamr@2: #pragma inline_depth(511) williamr@2: #pragma inline_recursion(on) williamr@2: #endif williamr@2: williamr@2: #if defined(__MWERKS__) williamr@2: #pragma inline_depth(511) williamr@2: #endif williamr@2: williamr@2: /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 williamr@2: // iserializer.hpp: interface for serialization system. williamr@2: williamr@2: // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . williamr@2: // Use, modification and distribution is subject to the Boost Software williamr@2: // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: williamr@2: // See http://www.boost.org for updates, documentation, and revision history. williamr@2: williamr@2: #include <new> // for placement new williamr@2: #include <memory> // for auto_ptr williamr@2: #include <cstddef> // size_t williamr@2: williamr@2: #include <boost/config.hpp> williamr@2: #include <boost/detail/workaround.hpp> williamr@2: #if defined(BOOST_NO_STDC_NAMESPACE) williamr@2: namespace std{ williamr@2: using ::size_t; williamr@2: } // namespace std williamr@2: #endif williamr@2: #include <boost/throw_exception.hpp> williamr@2: #include <boost/smart_cast.hpp> williamr@2: #include <boost/static_assert.hpp> williamr@2: #include <boost/static_warning.hpp> williamr@2: #include <boost/detail/no_exceptions_support.hpp> williamr@2: williamr@2: #include <boost/type_traits/is_pointer.hpp> williamr@2: #include <boost/type_traits/is_fundamental.hpp> williamr@2: #include <boost/type_traits/is_enum.hpp> williamr@2: #include <boost/type_traits/is_const.hpp> williamr@2: #include <boost/type_traits/remove_const.hpp> williamr@2: #include <boost/serialization/is_abstract.hpp> williamr@2: williamr@2: #include <boost/mpl/eval_if.hpp> williamr@2: #include <boost/mpl/if.hpp> williamr@2: #include <boost/mpl/identity.hpp> williamr@2: #include <boost/mpl/or.hpp> williamr@2: #include <boost/mpl/and.hpp> williamr@2: #include <boost/mpl/less.hpp> williamr@2: #include <boost/mpl/greater_equal.hpp> williamr@2: #include <boost/mpl/int.hpp> williamr@2: #include <boost/mpl/list.hpp> williamr@2: #include <boost/mpl/empty.hpp> williamr@2: #include <boost/mpl/not.hpp> williamr@2: williamr@2: #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO williamr@2: #include <boost/serialization/extended_type_info_typeid.hpp> williamr@2: #endif williamr@2: // the following is need only for dynamic cast of polymorphic pointers williamr@2: #include <boost/archive/detail/basic_iarchive.hpp> williamr@2: #include <boost/archive/detail/basic_iserializer.hpp> williamr@2: #include <boost/archive/detail/archive_pointer_iserializer.hpp> williamr@2: #include <boost/archive/archive_exception.hpp> williamr@2: williamr@2: #include <boost/serialization/force_include.hpp> williamr@2: #include <boost/serialization/serialization.hpp> williamr@2: #include <boost/serialization/version.hpp> williamr@2: #include <boost/serialization/level.hpp> williamr@2: #include <boost/serialization/tracking.hpp> williamr@2: #include <boost/serialization/type_info_implementation.hpp> williamr@2: #include <boost/serialization/nvp.hpp> williamr@2: #include <boost/serialization/binary_object.hpp> williamr@2: #include <boost/serialization/void_cast.hpp> williamr@2: williamr@2: namespace boost { williamr@2: williamr@2: namespace serialization { williamr@2: class extended_type_info; williamr@2: } // namespace serialization williamr@2: williamr@2: namespace archive { williamr@2: williamr@2: // an accessor to permit friend access to archives. Needed because williamr@2: // some compilers don't handle friend templates completely williamr@2: class load_access { williamr@2: public: williamr@2: template<class Archive, class T> williamr@2: static void load_primitive(Archive &ar, T &t){ williamr@2: ar.load(t); williamr@2: } williamr@2: }; williamr@2: williamr@2: namespace detail { williamr@2: williamr@2: template<class Archive, class T> williamr@2: class iserializer : public basic_iserializer williamr@2: { williamr@2: private: williamr@2: virtual void destroy(/*const*/ void *address) const { williamr@2: boost::serialization::access::destroy(static_cast<T *>(address)); williamr@2: } williamr@2: // private constructor to inhibit any existence other than the williamr@2: // static one williamr@2: explicit iserializer() : williamr@2: basic_iserializer( williamr@2: * boost::serialization::type_info_implementation<T>::type::get_instance() williamr@2: ) williamr@2: {} williamr@2: public: williamr@2: virtual BOOST_DLLEXPORT void load_object_data( williamr@2: basic_iarchive & ar, williamr@2: void *x, williamr@2: const unsigned int file_version williamr@2: ) const BOOST_USED ; williamr@2: virtual bool class_info() const { williamr@2: return boost::serialization::implementation_level<T>::value williamr@2: >= boost::serialization::object_class_info; williamr@2: } williamr@2: virtual bool tracking(const unsigned int flags) const { williamr@2: // if(0 != (flags & no_tracking)) williamr@2: // return false; williamr@2: return boost::serialization::tracking_level<T>::value williamr@2: == boost::serialization::track_always williamr@2: || boost::serialization::tracking_level<T>::value williamr@2: == boost::serialization::track_selectivly williamr@2: && serialized_as_pointer(); williamr@2: } williamr@2: virtual unsigned int version() const { williamr@2: return ::boost::serialization::version<T>::value; williamr@2: } williamr@2: virtual bool is_polymorphic() const { williamr@2: typedef BOOST_DEDUCED_TYPENAME williamr@2: boost::serialization::type_info_implementation< williamr@2: T williamr@2: >::type::is_polymorphic::type typex; williamr@2: return typex::value; williamr@2: } williamr@2: static iserializer & instantiate(){ williamr@2: static iserializer instance; williamr@2: return instance; williamr@2: } williamr@2: virtual ~iserializer(){}; williamr@2: }; williamr@2: williamr@2: template<class Archive, class T> williamr@2: BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data( williamr@2: basic_iarchive & ar, williamr@2: void *x, williamr@2: const unsigned int file_version williamr@2: ) const { williamr@2: // make sure call is routed through the higest interface that might williamr@2: // be specialized by the user. williamr@2: boost::serialization::serialize_adl( williamr@2: boost::smart_cast_reference<Archive &>(ar), williamr@2: * static_cast<T *>(x), williamr@2: file_version williamr@2: ); williamr@2: } williamr@2: williamr@2: // instantiation of this template creates a static object. Note inversion of williamr@2: // normal argument order to workaround bizarre error in MSVC 6.0 which only williamr@2: // manifests iftself during compiler time. williamr@2: template<class T, class Archive> williamr@2: class pointer_iserializer : public archive_pointer_iserializer<Archive> williamr@2: { williamr@2: private: williamr@2: virtual const basic_iserializer & get_basic_serializer() const { williamr@2: return iserializer<Archive, T>::instantiate(); williamr@2: } williamr@2: virtual BOOST_DLLEXPORT void load_object_ptr( williamr@2: basic_iarchive & ar, williamr@2: void * & x, williamr@2: const unsigned int file_version williamr@2: ) const BOOST_USED; williamr@2: #if defined(__GNUC__) || ( defined(BOOST_MSVC) && (_MSC_VER <= 1300) ) williamr@2: public: williamr@2: #endif williamr@2: // private constructor to inhibit any existence other than the williamr@2: // static one. Note GCC doesn't permit constructor to be private williamr@2: explicit BOOST_DLLEXPORT pointer_iserializer() BOOST_USED; williamr@2: static const pointer_iserializer instance; williamr@2: public: williamr@2: // at least one compiler (CW) seems to require that serialize_adl williamr@2: // be explicitly instantiated. Still under investigation. williamr@2: #if ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) williamr@2: void (* const m)(Archive &, T &, const unsigned); williamr@2: boost::serialization::extended_type_info * (* e)(); williamr@2: #endif williamr@2: static BOOST_DLLEXPORT const pointer_iserializer & instantiate() BOOST_USED; williamr@2: virtual ~pointer_iserializer(){}; williamr@2: }; williamr@2: williamr@2: template<class T, class Archive> williamr@2: BOOST_DLLEXPORT const pointer_iserializer<T, Archive> & williamr@2: pointer_iserializer<T, Archive>::instantiate() { williamr@2: return instance; williamr@2: } williamr@2: williamr@2: // note: instances of this template to be constructed before the main williamr@2: // is called in order for things to be initialized properly. For this williamr@2: // reason, hiding the instance in a static function as was done above williamr@2: // won't work here so we created a free instance here. williamr@2: template<class T, class Archive> williamr@2: const pointer_iserializer<T, Archive> pointer_iserializer<T, Archive>::instance; williamr@2: williamr@2: // note trick to be sure that operator new is using class specific williamr@2: // version if such exists. Due to Peter Dimov. williamr@2: // note: the following fails if T has no default constructor. williamr@2: // otherwise it would have been ideal williamr@2: //struct heap_allocator : public T williamr@2: //{ williamr@2: // T * invoke(){ williamr@2: // return ::new(sizeof(T)); williamr@2: // } williamr@2: //} williamr@2: williamr@2: // note: this should really be a member of the load_ptr function williamr@2: // below but some compilers still complain about this. williamr@2: template<class T> williamr@2: struct heap_allocator williamr@2: { williamr@2: #if 0 williamr@2: // note: this fails on msvc 7.0 and gcc 3.2 williamr@2: template <class U, U x> struct test; williamr@2: typedef char* yes; williamr@2: typedef int* no; williamr@2: template <class U> williamr@2: yes has_op_new(U*, test<void* (*)(std::size_t), &U::operator new>* = 0); williamr@2: no has_op_new(...); williamr@2: williamr@2: template<class U> williamr@2: T * new_operator(U); williamr@2: williamr@2: T * new_operator(yes){ williamr@2: return (T::operator new)(sizeof(T)); williamr@2: } williamr@2: T * new_operator(no){ williamr@2: return static_cast<T *>(operator new(sizeof(T))); williamr@2: } williamr@2: static T * invoke(){ williamr@2: return new_operator(has_op_new(static_cast<T *>(NULL))); williamr@2: } williamr@2: #else williamr@2: // while this doesn't handle operator new overload for class T williamr@2: static T * invoke(){ williamr@2: return static_cast<T *>(operator new(sizeof(T))); williamr@2: } williamr@2: #endif williamr@2: }; williamr@2: williamr@2: // due to Martin Ecker williamr@2: template <typename T> williamr@2: class auto_ptr_with_deleter williamr@2: { williamr@2: public: williamr@2: explicit auto_ptr_with_deleter(T* p) : williamr@2: m_p(p) williamr@2: {} williamr@2: ~auto_ptr_with_deleter(){ williamr@2: if (m_p) williamr@2: boost::serialization::access::destroy(m_p); williamr@2: } williamr@2: T* get() const { williamr@2: return m_p; williamr@2: } williamr@2: williamr@2: T* release() { williamr@2: T* p = m_p; williamr@2: m_p = NULL; williamr@2: return p; williamr@2: } williamr@2: private: williamr@2: T* m_p; williamr@2: }; williamr@2: williamr@2: template<class T, class Archive> williamr@2: BOOST_DLLEXPORT void pointer_iserializer<T, Archive>::load_object_ptr( williamr@2: basic_iarchive & ar, williamr@2: void * & x, williamr@2: const unsigned int file_version williamr@2: ) const { williamr@2: Archive & ar_impl = boost::smart_cast_reference<Archive &>(ar); williamr@2: williamr@2: // if(0 != (ar.get_flags() & no_object_creation)){ williamr@2: // ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(x)); williamr@2: // return; williamr@2: // } williamr@2: williamr@2: auto_ptr_with_deleter<T> ap(heap_allocator<T>::invoke()); williamr@2: if(NULL == ap.get()) williamr@2: boost::throw_exception(std::bad_alloc()) ; williamr@2: williamr@2: T * t = ap.get(); williamr@2: x = t; williamr@2: williamr@2: // catch exception during load_construct_data so that we don't williamr@2: // automatically delete the t which is most likely not fully williamr@2: // constructed williamr@2: BOOST_TRY { williamr@2: // this addresses an obscure situtation that occurs when williamr@2: // load_constructor de-serializes something through a pointer. williamr@2: ar.next_object_pointer(t); williamr@2: boost::serialization::load_construct_data_adl<Archive, T>( williamr@2: ar_impl, williamr@2: t, williamr@2: file_version williamr@2: ); williamr@2: } williamr@2: BOOST_CATCH(...){ williamr@2: BOOST_RETHROW; williamr@2: } williamr@2: BOOST_CATCH_END williamr@2: williamr@2: ar_impl >> boost::serialization::make_nvp(NULL, * t); williamr@2: ap.release(); williamr@2: } williamr@2: williamr@2: template<class T, class Archive> williamr@2: #if ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) williamr@2: BOOST_DLLEXPORT pointer_iserializer<T, Archive>::pointer_iserializer() : williamr@2: archive_pointer_iserializer<Archive>( williamr@2: * boost::serialization::type_info_implementation<T>::type::get_instance() williamr@2: ), williamr@2: m(boost::serialization::serialize_adl<Archive, T>), williamr@2: e(boost::serialization::type_info_implementation<T>::type::get_instance) williamr@2: #else williamr@2: BOOST_DLLEXPORT pointer_iserializer<T, Archive>::pointer_iserializer() : williamr@2: archive_pointer_iserializer<Archive>( williamr@2: * boost::serialization::type_info_implementation<T>::type::get_instance() williamr@2: ) williamr@2: #endif williamr@2: { williamr@2: iserializer<Archive, T> & bis = iserializer<Archive, T>::instantiate(); williamr@2: bis.set_bpis(this); williamr@2: } williamr@2: williamr@2: template<class Archive, class T> williamr@2: struct load_non_pointer_type { williamr@2: // note this bounces the call right back to the archive williamr@2: // with no runtime overhead williamr@2: struct load_primitive { williamr@2: static void invoke(Archive & ar, T & t){ williamr@2: load_access::load_primitive(ar, t); williamr@2: } williamr@2: }; williamr@2: // note this bounces the call right back to the archive williamr@2: // with no runtime overhead williamr@2: struct load_only { williamr@2: static void invoke(Archive & ar, T & t){ williamr@2: // short cut to user's serializer williamr@2: // make sure call is routed through the higest interface that might williamr@2: // be specialized by the user. williamr@2: boost::serialization::serialize_adl( williamr@2: ar, t, boost::serialization::version<T>::value williamr@2: ); williamr@2: } williamr@2: }; williamr@2: williamr@2: // note this save class information including version williamr@2: // and serialization level to the archive williamr@2: struct load_standard { williamr@2: static void invoke(Archive &ar, T &t){ williamr@2: //BOOST_STATIC_ASSERT(! boost::is_const<T>::value); williamr@2: // borland - for some reason T is const here - even though williamr@2: // its not called that way - so fix it her williamr@2: typedef BOOST_DEDUCED_TYPENAME boost::remove_const<T>::type typex; williamr@2: void * x = & const_cast<typex &>(t); williamr@2: ar.load_object(x, iserializer<Archive, T>::instantiate()); williamr@2: } williamr@2: }; williamr@2: williamr@2: struct load_conditional { williamr@2: static void invoke(Archive &ar, T &t){ williamr@2: //if(0 == (ar.get_flags() & no_tracking)) williamr@2: load_standard::invoke(ar, t); williamr@2: //else williamr@2: // load_only::invoke(ar, t); williamr@2: } williamr@2: }; williamr@2: williamr@2: typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< williamr@2: // if its primitive williamr@2: mpl::equal_to< williamr@2: boost::serialization::implementation_level<T>, williamr@2: mpl::int_<boost::serialization::primitive_type> williamr@2: >, williamr@2: mpl::identity<load_primitive>, williamr@2: // else williamr@2: BOOST_DEDUCED_TYPENAME mpl::eval_if< williamr@2: // class info / version williamr@2: mpl::greater_equal< williamr@2: boost::serialization::implementation_level<T>, williamr@2: mpl::int_<boost::serialization::object_class_info> williamr@2: >, williamr@2: // do standard load williamr@2: mpl::identity<load_standard>, williamr@2: // else williamr@2: BOOST_DEDUCED_TYPENAME mpl::eval_if< williamr@2: // no tracking williamr@2: mpl::equal_to< williamr@2: boost::serialization::tracking_level<T>, williamr@2: mpl::int_<boost::serialization::track_never> williamr@2: >, williamr@2: // do a fast load williamr@2: mpl::identity<load_only>, williamr@2: // else williamr@2: // do a fast load only tracking is turned off williamr@2: mpl::identity<load_conditional> williamr@2: > > >::type typex; williamr@2: williamr@2: static void invoke(Archive & ar, T &t){ williamr@2: BOOST_STATIC_ASSERT(( williamr@2: mpl::greater_equal< williamr@2: boost::serialization::implementation_level<T>, williamr@2: mpl::int_<boost::serialization::primitive_type> williamr@2: >::value williamr@2: )); williamr@2: typex::invoke(ar, t); williamr@2: } williamr@2: }; williamr@2: williamr@2: template<class Archive, class Tptr> williamr@2: struct load_pointer_type { williamr@2: template<class T> williamr@2: struct abstract williamr@2: { williamr@2: static const basic_pointer_iserializer * register_type(Archive & /* ar */){ williamr@2: #if ! defined(__BORLANDC__) williamr@2: typedef BOOST_DEDUCED_TYPENAME williamr@2: boost::serialization::type_info_implementation<T>::type::is_polymorphic typex; williamr@2: // it has? to be polymorphic williamr@2: BOOST_STATIC_ASSERT(typex::value); williamr@2: #endif williamr@2: return static_cast<basic_pointer_iserializer *>(NULL); williamr@2: } williamr@2: }; williamr@2: williamr@2: template<class T> williamr@2: struct non_abstract williamr@2: { williamr@2: static const basic_pointer_iserializer * register_type(Archive & ar){ williamr@2: return ar.register_type(static_cast<T *>(NULL)); williamr@2: } williamr@2: }; williamr@2: williamr@2: template<class T> williamr@2: static const basic_pointer_iserializer * register_type(Archive &ar, T & /*t*/){ williamr@2: // there should never be any need to load an abstract polymorphic williamr@2: // class pointer. Inhibiting code generation for this williamr@2: // permits abstract base classes to be used - note: exception williamr@2: // virtual serialize functions used for plug-ins williamr@2: typedef BOOST_DEDUCED_TYPENAME williamr@2: mpl::eval_if< williamr@2: serialization::is_abstract<T>, williamr@2: mpl::identity<abstract<T> >, williamr@2: mpl::identity<non_abstract<T> > williamr@2: >::type typex; williamr@2: return typex::register_type(ar); williamr@2: } williamr@2: williamr@2: template<class T> williamr@2: static T * pointer_tweak( williamr@2: const boost::serialization::extended_type_info & eti, williamr@2: void * t, williamr@2: T & williamr@2: ) { williamr@2: // tweak the pointer back to the base class williamr@2: return static_cast<T *>( williamr@2: boost::serialization::void_upcast( williamr@2: eti, williamr@2: * boost::serialization::type_info_implementation<T>::type::get_instance(), williamr@2: t williamr@2: ) williamr@2: ); williamr@2: } williamr@2: williamr@2: static void invoke(Archive & ar, Tptr & t){ williamr@2: const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t); williamr@2: const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer( williamr@2: * reinterpret_cast<void **>(&t), williamr@2: bpis_ptr, williamr@2: archive_pointer_iserializer<Archive>::find williamr@2: ); williamr@2: // if the pointer isn't that of the base class williamr@2: if(newbpis_ptr != bpis_ptr){ williamr@2: t = pointer_tweak(newbpis_ptr->get_eti(), t, *t); williamr@2: } williamr@2: } williamr@2: }; williamr@2: williamr@2: template<class Archive, class T> williamr@2: struct load_enum_type { williamr@2: static void invoke(Archive &ar, T &t){ williamr@2: // convert integers to correct enum to load williamr@2: int i; williamr@2: ar >> boost::serialization::make_nvp(NULL, i); williamr@2: t = static_cast<T>(i); williamr@2: } williamr@2: }; williamr@2: williamr@2: template<class Archive, class T> williamr@2: struct load_array_type { williamr@2: static void invoke(Archive &ar, T &t){ williamr@2: // convert integers to correct enum to load williamr@2: int current_count = sizeof(t) / ( williamr@2: static_cast<char *>(static_cast<void *>(&t[1])) williamr@2: - static_cast<char *>(static_cast<void *>(&t[0])) williamr@2: ); williamr@2: int count; williamr@2: ar >> BOOST_SERIALIZATION_NVP(count); williamr@2: if(count > current_count) williamr@2: boost::throw_exception(archive::archive_exception( williamr@2: boost::archive::archive_exception::array_size_too_short williamr@2: )); williamr@2: int i; williamr@2: for(i = 0; i < count; ++i) williamr@2: ar >> boost::serialization::make_nvp("item", t[i]); williamr@2: } williamr@2: }; williamr@2: williamr@2: // note bogus arguments to workaround msvc 6 silent runtime failure williamr@2: template<class Archive, class T> williamr@2: BOOST_DLLEXPORT williamr@2: inline const basic_pointer_iserializer & williamr@2: instantiate_pointer_iserializer( williamr@2: Archive * /* ar = NULL */, williamr@2: T * /* t = NULL */ williamr@2: ) BOOST_USED; williamr@2: williamr@2: template<class Archive, class T> williamr@2: BOOST_DLLEXPORT williamr@2: inline const basic_pointer_iserializer & williamr@2: instantiate_pointer_iserializer( williamr@2: Archive * /* ar = NULL */, williamr@2: T * /* t = NULL */ williamr@2: ){ williamr@2: // note: reversal of order of arguments to work around msvc 6.0 bug williamr@2: // that manifests itself while trying to link. williamr@2: return pointer_iserializer<T, Archive>::instantiate(); williamr@2: } williamr@2: williamr@2: } // detail williamr@2: williamr@2: template<class Archive, class T> williamr@2: inline void load(Archive &ar, T &t){ williamr@2: // if this assertion trips. It means we're trying to load a williamr@2: // const object with a compiler that doesn't have correct williamr@2: // funtion template ordering. On other compilers, this is williamr@2: // handled below. williamr@2: BOOST_STATIC_ASSERT(! boost::is_const<T>::value); williamr@2: typedef williamr@2: BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer<T>, williamr@2: mpl::identity<detail::load_pointer_type<Archive, T> > williamr@2: ,//else williamr@2: BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array<T>, williamr@2: mpl::identity<detail::load_array_type<Archive, T> > williamr@2: ,//else williamr@2: BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum<T>, williamr@2: mpl::identity<detail::load_enum_type<Archive, T> > williamr@2: ,//else williamr@2: mpl::identity<detail::load_non_pointer_type<Archive, T> > williamr@2: > williamr@2: > williamr@2: >::type typex; williamr@2: typex::invoke(ar, t); williamr@2: } williamr@2: williamr@2: // BORLAND williamr@2: #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560)) williamr@2: // borland has a couple fo problems williamr@2: // a) if function is partiall specialized - see below williamr@2: // const paramters are transformed to non-const ones williamr@2: // b) implementation of base_object can't be made to work williamr@2: // correctly which results in all base_object s being const. williamr@2: // So, strip off the const for borland. This breaks the trap williamr@2: // for loading const objects - but I see no alternative williamr@2: template<class Archive, class T> williamr@2: inline void load(Archive &ar, const T & t){ williamr@2: load(ar, const_cast<T &>(t)); williamr@2: } williamr@2: #endif williamr@2: williamr@2: // let wrappers through. (Someday implement is_wrapper) williamr@2: #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING williamr@2: template<class Archive, class T> williamr@2: inline void load(Archive &ar, const serialization::nvp<T> &t){ williamr@2: boost::archive::load(ar, const_cast<serialization::nvp<T> &>(t)); williamr@2: } williamr@2: template<class Archive> williamr@2: inline void load(Archive &ar, const serialization::binary_object &t){ williamr@2: boost::archive::load(ar, const_cast<serialization::binary_object &>(t)); williamr@2: } williamr@2: williamr@2: //template<class Archive, class T> williamr@2: //inline void load(Archive &ar, const serialization::binary_object &t){ williamr@2: // load(ar, const_cast<binary_object &>(t)); williamr@2: //} williamr@2: #endif williamr@2: williamr@2: } // namespace archive williamr@2: } // namespace boost williamr@2: williamr@2: #endif // BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP