williamr@2: #ifndef BOOST_SERIALIZATION_EXPORT_HPP williamr@2: #define BOOST_SERIALIZATION_EXPORT_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: #endif williamr@2: williamr@2: /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 williamr@2: // export.hpp: set traits of classes to be serialized 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: // implementation of class export functionality. This is an alternative to williamr@2: // "forward declaration" method to provoke instantiation of derived classes williamr@2: // that are to be serialized through pointers. williamr@2: williamr@2: #include williamr@2: williamr@2: #include williamr@2: williamr@2: // if no archive headers have been included this is a no op williamr@2: // this is to permit BOOST_EXPORT etc to be included in a williamr@2: // file declaration header williamr@2: #if ! defined(BOOST_ARCHIVE_BASIC_ARCHIVE_HPP) williamr@2: #define BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, K, ASEQ) williamr@2: williamr@2: #else williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: namespace boost { williamr@2: namespace archive { williamr@2: namespace detail { williamr@2: williamr@2: // forward template declarations williamr@2: class basic_pointer_iserializer; williamr@2: template williamr@2: BOOST_DLLEXPORT const basic_pointer_iserializer & williamr@2: instantiate_pointer_iserializer(Archive * ar, T *) BOOST_USED; williamr@2: williamr@2: class basic_pointer_oserializer; williamr@2: template williamr@2: BOOST_DLLEXPORT const basic_pointer_oserializer & williamr@2: instantiate_pointer_oserializer(Archive * ar, T *) BOOST_USED; williamr@2: williamr@2: namespace export_impl williamr@2: { williamr@2: struct nothing{ williamr@2: static void instantiate(){} williamr@2: }; williamr@2: williamr@2: template williamr@2: struct archive { williamr@2: struct i { williamr@2: static void invoke(){ williamr@2: instantiate_pointer_iserializer( williamr@2: static_cast(NULL), williamr@2: static_cast(NULL) williamr@2: ); williamr@2: } williamr@2: }; williamr@2: struct o { williamr@2: static void invoke(){ williamr@2: instantiate_pointer_oserializer( williamr@2: static_cast(NULL), williamr@2: static_cast(NULL) williamr@2: ); williamr@2: } williamr@2: }; williamr@2: static void instantiate(){ williamr@2: #if defined(__GNUC__) && (__GNUC__ >= 3) williamr@2: BOOST_STATIC_ASSERT( williamr@2: Archive::is_loading::value || Archive::is_saving::value williamr@2: ); williamr@2: #endif williamr@2: typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< williamr@2: BOOST_DEDUCED_TYPENAME Archive::is_saving, williamr@2: mpl::identity, williamr@2: // else williamr@2: BOOST_DEDUCED_TYPENAME mpl::eval_if< williamr@2: BOOST_DEDUCED_TYPENAME Archive::is_loading, williamr@2: mpl::identity, williamr@2: // else williamr@2: mpl::identity williamr@2: > >::type typex; williamr@2: typex::invoke(); williamr@2: } williamr@2: }; williamr@2: williamr@2: template williamr@2: struct for_each_archive { williamr@2: private: williamr@2: typedef BOOST_DEDUCED_TYPENAME mpl::pop_front::type tail; williamr@2: typedef BOOST_DEDUCED_TYPENAME mpl::front::type head; williamr@2: public: williamr@2: static void instantiate(){ williamr@2: archive::instantiate(); williamr@2: typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< williamr@2: mpl::empty, williamr@2: mpl::identity, williamr@2: mpl::identity > williamr@2: >::type typex; williamr@2: typex::instantiate(); williamr@2: } williamr@2: }; williamr@2: williamr@2: } // namespace export_impl williamr@2: williamr@2: // strictly conforming williamr@2: template williamr@2: struct export_generator { williamr@2: export_generator(){ williamr@2: export_impl::for_each_archive::instantiate(); williamr@2: } williamr@2: static const export_generator instance; williamr@2: }; williamr@2: williamr@2: template williamr@2: const export_generator williamr@2: export_generator::instance; williamr@2: williamr@2: // instantiation of this template creates a static object. williamr@2: template williamr@2: struct guid_initializer { williamr@2: typedef BOOST_DEDUCED_TYPENAME boost::serialization::type_info_implementation::type eti_type; williamr@2: static void export_register(const char *key){ williamr@2: eti_type::export_register(key); williamr@2: } williamr@2: static const guid_initializer instance; williamr@2: guid_initializer(const char *key = 0) BOOST_USED ; williamr@2: }; williamr@2: williamr@2: template williamr@2: guid_initializer::guid_initializer(const char *key){ williamr@2: if(0 != key) williamr@2: export_register(key); williamr@2: } williamr@2: williamr@2: template williamr@2: const guid_initializer guid_initializer::instance; williamr@2: williamr@2: // only gcc seems to be able to explicitly instantiate a static instance. williamr@2: // but all can instantiate a function that refers to a static instance williamr@2: williamr@2: // the following optimization - inhibiting explicit instantiation for abstract williamr@2: // classes breaks msvc compliles williamr@2: template williamr@2: struct export_instance { williamr@2: struct abstract { williamr@2: static const export_generator * williamr@2: invoke(){ williamr@2: return 0; williamr@2: } williamr@2: }; williamr@2: struct not_abstract { williamr@2: static const export_generator * williamr@2: invoke(){ williamr@2: return & export_generator::instance; williamr@2: } williamr@2: }; williamr@2: }; williamr@2: williamr@2: template williamr@2: BOOST_DLLEXPORT williamr@2: std::pair *, const guid_initializer *> williamr@2: export_instance_invoke() { williamr@2: typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< williamr@2: serialization::is_abstract, williamr@2: mpl::identity::abstract>, williamr@2: mpl::identity::not_abstract> williamr@2: >::type typex; williamr@2: return std::pair *, const guid_initializer *>( williamr@2: typex::invoke(), williamr@2: & guid_initializer::instance williamr@2: ); williamr@2: } williamr@2: williamr@2: template williamr@2: struct export_archives { williamr@2: struct empty_archive_list { williamr@2: static BOOST_DLLEXPORT williamr@2: std::pair *, const guid_initializer *> williamr@2: invoke(){ williamr@2: return std::pair *, williamr@2: const guid_initializer *>(0, 0); williamr@2: } williamr@2: }; williamr@2: struct non_empty_archive_list { williamr@2: static BOOST_DLLEXPORT williamr@2: std::pair *, const guid_initializer *> williamr@2: invoke(){ williamr@2: return export_instance_invoke(); williamr@2: } williamr@2: }; williamr@2: }; williamr@2: williamr@2: template williamr@2: BOOST_DLLEXPORT williamr@2: std::pair *, const guid_initializer *> williamr@2: export_archives_invoke(T &, ASeq &){ williamr@2: typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< williamr@2: mpl::empty, williamr@2: mpl::identity::empty_archive_list>, williamr@2: mpl::identity::non_empty_archive_list> williamr@2: >::type typex; williamr@2: return typex::invoke(); williamr@2: } williamr@2: williamr@2: } // namespace detail williamr@2: } // namespace archive williamr@2: } // namespace boost williamr@2: williamr@2: #define BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, K, ASEQ) \ williamr@2: namespace boost { \ williamr@2: namespace archive { \ williamr@2: namespace detail { \ williamr@2: template<> \ williamr@2: const guid_initializer< T > \ williamr@2: guid_initializer< T >::instance(K); \ williamr@2: template \ williamr@2: BOOST_DLLEXPORT \ williamr@2: std::pair *, const guid_initializer< T > *> \ williamr@2: export_archives_invoke(T &, ASEQ &); \ williamr@2: } } } \ williamr@2: /**/ williamr@2: williamr@2: #endif williamr@2: williamr@2: // check for unnecessary export. T isn't polymorphic so there is no williamr@2: // need to export it. williamr@2: #define BOOST_CLASS_EXPORT_CHECK(T) \ williamr@2: BOOST_STATIC_WARNING( \ williamr@2: boost::serialization::type_info_implementation< T > \ williamr@2: ::type::is_polymorphic::value \ williamr@2: ); \ williamr@2: /**/ williamr@2: williamr@2: // the default list of archives types for which code id generated williamr@2: #define BOOST_CLASS_EXPORT_GUID(T, K) \ williamr@2: BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST( \ williamr@2: T, \ williamr@2: K, \ williamr@2: boost::archive::detail::known_archive_types::type \ williamr@2: ) \ williamr@2: /**/ williamr@2: williamr@2: // the default exportable class identifier is the class name williamr@2: #define BOOST_CLASS_EXPORT_ARCHIVE_LIST(T, ASEQ) \ williamr@2: BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, BOOST_PP_STRINGIZE(T), A) williamr@2: williamr@2: // the default exportable class identifier is the class name williamr@2: // the default list of archives types for which code id generated williamr@2: // are the originally included with this serialization system williamr@2: #define BOOST_CLASS_EXPORT(T) \ williamr@2: BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST( \ williamr@2: T, \ williamr@2: BOOST_PP_STRINGIZE(T), \ williamr@2: boost::archive::detail::known_archive_types::type \ williamr@2: ) \ williamr@2: /**/ williamr@2: williamr@2: #endif // BOOST_SERIALIZATION_EXPORT_HPP