Re: [Boost-bugs] [Boost C++ Libraries] #7047: Deriving custom archive classes from boost::archive::text_oarchive_impl and boost::archive::text_iarchive_impl

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #7047: Deriving custom archive classes from boost::archive::text_oarchive_impl and boost::archive::text_iarchive_impl
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2013-08-24 14:09:23


#7047: Deriving custom archive classes from boost::archive::text_oarchive_impl and
boost::archive::text_iarchive_impl
-------------------------------+---------------------------
  Reporter: zachais.vawter@… | Owner: ramey
      Type: Bugs | Status: new
 Milestone: To Be Determined | Component: serialization
   Version: Boost 1.48.0 | Severity: Problem
Resolution: | Keywords:
-------------------------------+---------------------------

Comment (by anonymous):

 I had the same problem tying to implement custom archive for my library.
 I've found a possible solution trick, it seems to works well so I'll share
 with you:

 There is no way to export a class with a modified serialization syntax in
 boost archive, so we have to avoid it at all.

 boost archive registration uses a properly overloaded function to make a
 pointer serialization type instance ( as in
 boost/archive/detail/register_archive.hpp )


 {{{
 # define BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive) \
 namespace boost { namespace archive { namespace detail { \
                                                                         \
 template <class Serializable> \
 BOOST_DEDUCED_TYPENAME _ptr_serialization_support<Archive,
 Serializable>::type \
 instantiate_ptr_serialization( Serializable*, Archive*, adl_tag );
 \
                                                                         \
 } } }
 }}}


 Note that adl_tag adds a cool overload feature that can be used to make
 boost able to look inside our implementation. Simply put a new
 registration declaration as this:


 {{{
 // ARCHIVES REGISTRATION //

 namespace MyLib {
 struct adl_tag {};
 }

 namespace boost { namespace archive { namespace detail {
 template <class Serializable>
 void instantiate_ptr_serialization(Serializable*, int, MyLib::adl_tag ) {}
 } } }

 # define MYLIB_SERIALIZATION_REGISTER_ARCHIVE(_Archive)
 \
 namespace boost { namespace archive { namespace detail { \
 template <class Serializable> \
 BOOST_DEDUCED_TYPENAME _ptr_serialization_support<_Archive,
 Serializable>::type \
 instantiate_ptr_serialization( Serializable*, _Archive*, MyLib::adl_tag );
 } } }
 }}}


 Now you have to make your own EXPORT macro as in
 (/boost/serialization/export.hpp):


 {{{
 namespace MyLib {
 namespace extra_detail {

 template<class T>
 struct guid_initializer
 {
     void export_guid(mpl::false_) const {
         // generates the statically-initialized objects whose constructors
         // register the information allowing serialization of T objects
         // through pointers to their base classes.
         boost::archive::detail::
                 instantiate_ptr_serialization((T*)0, 0,
                                               MyLib::adl_tag());
     }
     void export_guid(mpl::true_) const {
     }
     guid_initializer const & export_guid() const {
         BOOST_STATIC_WARNING(boost::is_polymorphic< T >::value);
         // 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);
         export_guid(boost::serialization::is_abstract< T >());
         return *this;
     }
 };

 template<typename T>
 struct init_guid;

 } // extra_detail
 } // namespace MyLib



 #define MYLIB_CLASS_EXPORT_IMPLEMENT(T) \
     namespace MyLib { \
     namespace extra_detail { \
     template<> \
     struct init_guid< T > { \
         static guid_initializer< T > const & g; \
     }; \
     guid_initializer< T > const & init_guid< T >::g = \
         ::boost::serialization::singleton< \
             guid_initializer< T > \
>::get_mutable_instance().export_guid(); \
     }} \
 /**/
 }}}


 Ok it's all, now you can define your custom archive and register it with:


 {{{
 MYLIB_SERIALIZATION_REGISTER_ARCHIVE(MyLib::xml_iarchive)

 }}}

 and anytime you define a serialization for your class that has a
 particular syntax only readable by MyLib::custom_archive you can use your
 export implementation


 {{{
 BOOST_CLASS_EXPORT_KEY(MyClass) // in header
 MYLIB_CLASS_EXPORT_IMPLEMENT(MyClass) // in cpp

 }}}

 (Note that exporting of Key remains the same of boost ... )

 This is really cool because lets your custom archives and boost archives
 live together without errors.. Anytime you wants a boost serialization
 simply use BOOST_CLASS_EXPORT, and anytime you have your class to be
 serialized use MYLIB_CLASS_EXPORT.

 Hope that this could be useful !

 Andrea Rigoni Garola
 (OpenCMT - Cosmic Muon Tomography library)

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/7047#comment:3>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:13 UTC