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.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 | #include <iostream> |
46 | |
47 | namespace boost { |
48 | namespace archive { |
49 | namespace detail { |
50 | |
51 | class basic_pointer_iserializer; |
52 | class basic_pointer_oserializer; |
53 | |
54 | template<class Archive, class T> |
55 | class pointer_iserializer; |
56 | template<class Archive, class T> |
57 | class pointer_oserializer; |
58 | |
59 | template <class Archive, class Serializable> |
60 | struct export_impl |
61 | { |
62 | static const basic_pointer_iserializer & |
63 | enable_load(mpl::true_){ |
64 | return boost::serialization::singleton< |
65 | pointer_iserializer<Archive, Serializable> |
66 | >::get_const_instance(); |
67 | } |
68 | |
69 | static const basic_pointer_oserializer & |
70 | enable_save(mpl::true_){ |
71 | return boost::serialization::singleton< |
72 | pointer_oserializer<Archive, Serializable> |
73 | >::get_const_instance(); |
74 | } |
75 | inline static void enable_load(mpl::false_) {} |
76 | inline static void enable_save(mpl::false_) {} |
77 | }; |
78 | |
79 | // On many platforms, naming a specialization of this template is |
80 | // enough to cause its argument to be instantiated. |
81 | template <void(*)()> |
82 | struct instantiate_function {}; |
83 | |
84 | template <class Archive, class Serializable> |
85 | struct ptr_serialization_support |
86 | { |
87 | # if defined(BOOST_MSVC) || defined(__SUNPRO_CC) |
88 | virtual BOOST_DLLEXPORT void instantiate() BOOST_USED; |
89 | # else |
90 | static BOOST_DLLEXPORT void instantiate() BOOST_USED; |
91 | typedef instantiate_function< |
92 | &ptr_serialization_support::instantiate |
93 | > x; |
94 | # endif |
95 | }; |
96 | |
97 | template <class Archive, class Serializable> |
98 | BOOST_DLLEXPORT void |
99 | ptr_serialization_support<Archive,Serializable>::instantiate() |
100 | { |
101 | export_impl<Archive,Serializable>::enable_save( |
102 | typename Archive::is_saving() |
103 | ); |
104 | |
105 | export_impl<Archive,Serializable>::enable_load( |
106 | typename Archive::is_loading() |
107 | ); |
108 | } |
109 | |
110 | // Note INTENTIONAL usage of anonymous namespace in header. |
111 | // This was made this way so that export.hpp could be included |
112 | // in other headers. This is still under study. |
113 | |
114 | namespace extra_detail { |
115 | |
116 | template<class T> |
117 | struct |
118 | { |
119 | void (mpl::false_) const { |
120 | // generates the statically-initialized objects whose constructors |
121 | // register the information allowing serialization of T objects |
122 | // through pointers to their base classes. |
123 | instantiate_ptr_serialization((T*)0, 0, adl_tag()); |
124 | } |
125 | void (mpl::true_) const { |
126 | } |
127 | guid_initializer const & () const { |
128 | BOOST_STATIC_WARNING(boost::is_polymorphic< T >::value); |
129 | // note: exporting an abstract base class will have no effect |
130 | // and cannot be used to instantitiate serialization code |
131 | // (one might be using this in a DLL to instantiate code) |
132 | //BOOST_STATIC_WARNING(! boost::serialization::is_abstract< T >::value); |
133 | export_guid(boost::serialization::is_abstract< T >()); |
134 | return *this; |
135 | } |
136 | }; |
137 | |
138 | template<typename T> |
139 | struct ; |
140 | |
141 | } // anonymous |
142 | } // namespace detail |
143 | } // namespace archive |
144 | } // namespace boost |
145 | |
146 | #define BOOST_CLASS_EXPORT_IMPLEMENT(T) \ |
147 | namespace boost { \ |
148 | namespace archive { \ |
149 | namespace detail { \ |
150 | namespace extra_detail { \ |
151 | template<> \ |
152 | struct init_guid< T > { \ |
153 | static guid_initializer< T > const & g; \ |
154 | }; \ |
155 | guid_initializer< T > const & init_guid< T >::g = \ |
156 | ::boost::serialization::singleton< \ |
157 | guid_initializer< T > \ |
158 | >::get_mutable_instance().export_guid(); \ |
159 | }}}} \ |
160 | /**/ |
161 | |
162 | #define BOOST_CLASS_EXPORT_KEY2(T, K) \ |
163 | namespace boost { \ |
164 | namespace serialization { \ |
165 | template<> \ |
166 | struct guid_defined< T > : boost::mpl::true_ {}; \ |
167 | template<> \ |
168 | inline const char * guid< T >(){ \ |
169 | return K; \ |
170 | } \ |
171 | } /* serialization */ \ |
172 | } /* boost */ \ |
173 | /**/ |
174 | |
175 | #define BOOST_CLASS_EXPORT_KEY(T) \ |
176 | BOOST_CLASS_EXPORT_KEY2(T, BOOST_PP_STRINGIZE(T)) \ |
177 | /**/ |
178 | |
179 | #define BOOST_CLASS_EXPORT_GUID(T, K) \ |
180 | BOOST_CLASS_EXPORT_KEY2(T, K) \ |
181 | BOOST_CLASS_EXPORT_IMPLEMENT(T) \ |
182 | /**/ |
183 | |
184 | #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) |
185 | |
186 | // CodeWarrior fails to construct static members of class templates |
187 | // when they are instantiated from within templates, so on that |
188 | // compiler we ask users to specifically register base/derived class |
189 | // relationships for exported classes. On all other compilers, use of |
190 | // this macro is entirely optional. |
191 | # define BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(Base,Derived) \ |
192 | namespace { \ |
193 | static int BOOST_PP_CAT(boost_serialization_mwerks_init_, __LINE__) = \ |
194 | (::boost::archive::detail::instantiate_ptr_serialization((Derived*)0,0), 3); \ |
195 | static int BOOST_PP_CAT(boost_serialization_mwerks_init2_, __LINE__) = ( \ |
196 | ::boost::serialization::void_cast_register((Derived*)0,(Base*)0) \ |
197 | , 3); \ |
198 | } |
199 | |
200 | #else |
201 | |
202 | # define BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(Base,Derived) |
203 | |
204 | #endif |
205 | |
206 | // check for unnecessary export. T isn't polymorphic so there is no |
207 | // need to export it. |
208 | #define BOOST_CLASS_EXPORT_CHECK(T) \ |
209 | BOOST_STATIC_WARNING( \ |
210 | boost::is_polymorphic<U>::value \ |
211 | ); \ |
212 | /**/ |
213 | |
214 | // the default exportable class identifier is the class name |
215 | // the default list of archives types for which code id generated |
216 | // are the originally included with this serialization system |
217 | #define BOOST_CLASS_EXPORT(T) \ |
218 | BOOST_CLASS_EXPORT_GUID( \ |
219 | T, \ |
220 | BOOST_PP_STRINGIZE(T) \ |
221 | ) \ |
222 | /**/ |
223 | |
224 | #endif // BOOST_SERIALIZATION_EXPORT_HPP |
225 | |
226 | |