1 #ifndef BOOST_SERIALIZATION_EXPORT_HPP
2 #define BOOST_SERIALIZATION_EXPORT_HPP
3 
4 // MS compatible compilers support #pragma once
5 #if defined(_MSC_VER)
6 # pragma once
7 #endif
8 
9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
10 // export.hpp: set traits of classes to be serialized
11 
12 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
13 // Use, modification and distribution is subject to the Boost Software
14 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
15 // http://www.boost.org/LICENSE_1_0.txt)
16 
17 //  See http://www.boost.org for updates, documentation, and revision history.
18 
19 // (C) Copyright 2006 David Abrahams - http://www.boost.org.
20 // implementation of class export functionality.  This is an alternative to
21 // "forward declaration" method to provoke instantiation of derived classes
22 // that are to be serialized through pointers.
23 
24 #include <utility>
25 #include <cstddef> // NULL
26 
27 #include <boost/config.hpp>
28 #include <boost/static_assert.hpp>
29 #include <boost/preprocessor/stringize.hpp>
30 #include <boost/type_traits/is_polymorphic.hpp>
31 
32 #include <boost/mpl/assert.hpp>
33 #include <boost/mpl/and.hpp>
34 #include <boost/mpl/not.hpp>
35 #include <boost/mpl/bool_fwd.hpp>
36 
37 #include <boost/serialization/extended_type_info.hpp> // for guid_defined only
38 #include <boost/serialization/static_warning.hpp>
39 #include <boost/serialization/assume_abstract.hpp>
40 #include <boost/serialization/force_include.hpp>
41 #include <boost/serialization/singleton.hpp>
42 
43 #include <boost/archive/detail/register_archive.hpp>
44 
45 namespace boost {
46 namespace archive {
47 namespace detail {
48 
49 class basic_pointer_iserializer;
50 class basic_pointer_oserializer;
51 
52 template<class Archive, class T>
53 class pointer_iserializer;
54 template<class Archive, class T>
55 class pointer_oserializer;
56 
57 template <class Archive, class Serializable>
58 struct export_impl
59 {
60     static const basic_pointer_iserializer &
enable_loadboost::archive::detail::export_impl61     enable_load(mpl::true_){
62         return boost::serialization::singleton<
63             pointer_iserializer<Archive, Serializable>
64         >::get_const_instance();
65     }
66 
67     static const basic_pointer_oserializer &
enable_saveboost::archive::detail::export_impl68     enable_save(mpl::true_){
69         return boost::serialization::singleton<
70             pointer_oserializer<Archive, Serializable>
71         >::get_const_instance();
72     }
enable_loadboost::archive::detail::export_impl73     inline static void enable_load(mpl::false_) {}
enable_saveboost::archive::detail::export_impl74     inline static void enable_save(mpl::false_) {}
75 };
76 
77 // On many platforms, naming a specialization of this template is
78 // enough to cause its argument to be instantiated.
79 template <void(*)()>
80 struct instantiate_function {};
81 
82 template <class Archive, class Serializable>
83 struct ptr_serialization_support
84 {
85 # if defined(BOOST_MSVC) || defined(__SUNPRO_CC)
86     virtual BOOST_DLLEXPORT void instantiate() BOOST_USED;
87 # else
88     static BOOST_DLLEXPORT void instantiate() BOOST_USED;
89     typedef instantiate_function<
90         &ptr_serialization_support::instantiate
91     > x;
92 # endif
93 };
94 
95 template <class Archive, class Serializable>
96 BOOST_DLLEXPORT void
instantiate()97 ptr_serialization_support<Archive,Serializable>::instantiate()
98 {
99     export_impl<Archive,Serializable>::enable_save(
100         typename Archive::is_saving()
101     );
102 
103     export_impl<Archive,Serializable>::enable_load(
104         typename Archive::is_loading()
105     );
106 }
107 
108 // Note INTENTIONAL usage of anonymous namespace in header.
109 // This was made this way so that export.hpp could be included
110 // in other headers.  This is still under study.
111 
112 namespace extra_detail {
113 
114 template<class T>
115 struct guid_initializer
116 {
export_guidboost::archive::detail::extra_detail::guid_initializer117     void export_guid(mpl::false_) const {
118         // generates the statically-initialized objects whose constructors
119         // register the information allowing serialization of T objects
120         // through pointers to their base classes.
121         instantiate_ptr_serialization((T*)0, 0, adl_tag());
122     }
export_guidboost::archive::detail::extra_detail::guid_initializer123     void export_guid(mpl::true_) const {
124     }
export_guidboost::archive::detail::extra_detail::guid_initializer125     guid_initializer const & export_guid() const {
126         BOOST_STATIC_WARNING(boost::is_polymorphic< T >::value);
127         // note: exporting an abstract base class will have no effect
128         // and cannot be used to instantitiate serialization code
129         // (one might be using this in a DLL to instantiate code)
130         //BOOST_STATIC_WARNING(! boost::serialization::is_abstract< T >::value);
131         export_guid(boost::serialization::is_abstract< T >());
132         return *this;
133     }
134 };
135 
136 template<typename T>
137 struct init_guid;
138 
139 } // anonymous
140 } // namespace detail
141 } // namespace archive
142 } // namespace boost
143 
144 #define BOOST_CLASS_EXPORT_IMPLEMENT(T)                      \
145     namespace boost {                                        \
146     namespace archive {                                      \
147     namespace detail {                                       \
148     namespace extra_detail {                                 \
149     template<>                                               \
150     struct init_guid< T > {                                  \
151         static guid_initializer< T > const & g;              \
152     };                                                       \
153     guid_initializer< T > const & init_guid< T >::g =        \
154         ::boost::serialization::singleton<                   \
155             guid_initializer< T >                            \
156         >::get_mutable_instance().export_guid();             \
157     }}}}                                                     \
158 /**/
159 
160 #define BOOST_CLASS_EXPORT_KEY2(T, K)          \
161 namespace boost {                              \
162 namespace serialization {                      \
163 template<>                                     \
164 struct guid_defined< T > : boost::mpl::true_ {}; \
165 template<>                                     \
166 inline const char * guid< T >(){                 \
167     return K;                                  \
168 }                                              \
169 } /* serialization */                          \
170 } /* boost */                                  \
171 /**/
172 
173 #define BOOST_CLASS_EXPORT_KEY(T)                                      \
174     BOOST_CLASS_EXPORT_KEY2(T, BOOST_PP_STRINGIZE(T))                                                                  \
175 /**/
176 
177 #define BOOST_CLASS_EXPORT_GUID(T, K)                                  \
178 BOOST_CLASS_EXPORT_KEY2(T, K)                                          \
179 BOOST_CLASS_EXPORT_IMPLEMENT(T)                                        \
180 /**/
181 
182 #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
183 
184 // CodeWarrior fails to construct static members of class templates
185 // when they are instantiated from within templates, so on that
186 // compiler we ask users to specifically register base/derived class
187 // relationships for exported classes.  On all other compilers, use of
188 // this macro is entirely optional.
189 # define BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(Base,Derived)             \
190 namespace {                                                                    \
191   static int BOOST_PP_CAT(boost_serialization_mwerks_init_, __LINE__) =        \
192   (::boost::archive::detail::instantiate_ptr_serialization((Derived*)0,0), 3); \
193   static int BOOST_PP_CAT(boost_serialization_mwerks_init2_, __LINE__) = (     \
194       ::boost::serialization::void_cast_register((Derived*)0,(Base*)0)         \
195     , 3);                                                                      \
196 }
197 
198 #else
199 
200 # define BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(Base,Derived)
201 
202 #endif
203 
204 // check for unnecessary export.  T isn't polymorphic so there is no
205 // need to export it.
206 #define BOOST_CLASS_EXPORT_CHECK(T)                              \
207     BOOST_STATIC_WARNING(                                        \
208         boost::is_polymorphic<U>::value                          \
209     );                                                           \
210     /**/
211 
212 // the default exportable class identifier is the class name
213 // the default list of archives types for which code id generated
214 // are the originally included with this serialization system
215 #define BOOST_CLASS_EXPORT(T)                   \
216     BOOST_CLASS_EXPORT_GUID(                    \
217         T,                                      \
218         BOOST_PP_STRINGIZE(T)                   \
219     )                                           \
220     /**/
221 
222 #endif // BOOST_SERIALIZATION_EXPORT_HPP
223 
224