|
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) && (_MSC_VER >= 1020) |
|
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 // implementation of class export functionality. This is an alternative to |
|
20 // "forward declaration" method to provoke instantiation of derived classes |
|
21 // that are to be serialized through pointers. |
|
22 |
|
23 #include <utility> |
|
24 |
|
25 #include <boost/config.hpp> |
|
26 |
|
27 // if no archive headers have been included this is a no op |
|
28 // this is to permit BOOST_EXPORT etc to be included in a |
|
29 // file declaration header |
|
30 #if ! defined(BOOST_ARCHIVE_BASIC_ARCHIVE_HPP) |
|
31 #define BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, K, ASEQ) |
|
32 |
|
33 #else |
|
34 #include <boost/static_assert.hpp> |
|
35 #include <boost/preprocessor/stringize.hpp> |
|
36 #include <boost/mpl/eval_if.hpp> |
|
37 #include <boost/mpl/or.hpp> |
|
38 #include <boost/mpl/empty.hpp> |
|
39 #include <boost/mpl/front.hpp> |
|
40 #include <boost/mpl/pop_front.hpp> |
|
41 #include <boost/mpl/void.hpp> |
|
42 #include <boost/mpl/identity.hpp> |
|
43 |
|
44 #include <boost/archive/detail/known_archive_types.hpp> |
|
45 #include <boost/serialization/force_include.hpp> |
|
46 #include <boost/serialization/type_info_implementation.hpp> |
|
47 #include <boost/serialization/is_abstract.hpp> |
|
48 |
|
49 namespace boost { |
|
50 namespace archive { |
|
51 namespace detail { |
|
52 |
|
53 // forward template declarations |
|
54 class basic_pointer_iserializer; |
|
55 template<class Archive, class T> |
|
56 BOOST_DLLEXPORT const basic_pointer_iserializer & |
|
57 instantiate_pointer_iserializer(Archive * ar, T *) BOOST_USED; |
|
58 |
|
59 class basic_pointer_oserializer; |
|
60 template<class Archive, class T> |
|
61 BOOST_DLLEXPORT const basic_pointer_oserializer & |
|
62 instantiate_pointer_oserializer(Archive * ar, T *) BOOST_USED; |
|
63 |
|
64 namespace export_impl |
|
65 { |
|
66 struct nothing{ |
|
67 static void instantiate(){} |
|
68 }; |
|
69 |
|
70 template<class Archive, class T> |
|
71 struct archive { |
|
72 struct i { |
|
73 static void invoke(){ |
|
74 instantiate_pointer_iserializer( |
|
75 static_cast<Archive *>(NULL), |
|
76 static_cast<T *>(NULL) |
|
77 ); |
|
78 } |
|
79 }; |
|
80 struct o { |
|
81 static void invoke(){ |
|
82 instantiate_pointer_oserializer( |
|
83 static_cast<Archive *>(NULL), |
|
84 static_cast<T *>(NULL) |
|
85 ); |
|
86 } |
|
87 }; |
|
88 static void instantiate(){ |
|
89 #if defined(__GNUC__) && (__GNUC__ >= 3) |
|
90 BOOST_STATIC_ASSERT( |
|
91 Archive::is_loading::value || Archive::is_saving::value |
|
92 ); |
|
93 #endif |
|
94 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< |
|
95 BOOST_DEDUCED_TYPENAME Archive::is_saving, |
|
96 mpl::identity<o>, |
|
97 // else |
|
98 BOOST_DEDUCED_TYPENAME mpl::eval_if< |
|
99 BOOST_DEDUCED_TYPENAME Archive::is_loading, |
|
100 mpl::identity<i>, |
|
101 // else |
|
102 mpl::identity<nothing> |
|
103 > >::type typex; |
|
104 typex::invoke(); |
|
105 } |
|
106 }; |
|
107 |
|
108 template<class ASeq, class T> |
|
109 struct for_each_archive { |
|
110 private: |
|
111 typedef BOOST_DEDUCED_TYPENAME mpl::pop_front<ASeq>::type tail; |
|
112 typedef BOOST_DEDUCED_TYPENAME mpl::front<ASeq>::type head; |
|
113 public: |
|
114 static void instantiate(){ |
|
115 archive<head, T>::instantiate(); |
|
116 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< |
|
117 mpl::empty<tail>, |
|
118 mpl::identity<nothing>, |
|
119 mpl::identity<for_each_archive<tail, T> > |
|
120 >::type typex; |
|
121 typex::instantiate(); |
|
122 } |
|
123 }; |
|
124 |
|
125 } // namespace export_impl |
|
126 |
|
127 // strictly conforming |
|
128 template<class T, class ASeq> |
|
129 struct export_generator { |
|
130 export_generator(){ |
|
131 export_impl::for_each_archive<ASeq, T>::instantiate(); |
|
132 } |
|
133 static const export_generator instance; |
|
134 }; |
|
135 |
|
136 template<class T, class ASeq> |
|
137 const export_generator<T, ASeq> |
|
138 export_generator<T, ASeq>::instance; |
|
139 |
|
140 // instantiation of this template creates a static object. |
|
141 template<class T> |
|
142 struct guid_initializer { |
|
143 typedef BOOST_DEDUCED_TYPENAME boost::serialization::type_info_implementation<T>::type eti_type; |
|
144 static void export_register(const char *key){ |
|
145 eti_type::export_register(key); |
|
146 } |
|
147 static const guid_initializer instance; |
|
148 guid_initializer(const char *key = 0) BOOST_USED ; |
|
149 }; |
|
150 |
|
151 template<class T> |
|
152 guid_initializer<T>::guid_initializer(const char *key){ |
|
153 if(0 != key) |
|
154 export_register(key); |
|
155 } |
|
156 |
|
157 template<class T> |
|
158 const guid_initializer<T> guid_initializer<T>::instance; |
|
159 |
|
160 // only gcc seems to be able to explicitly instantiate a static instance. |
|
161 // but all can instantiate a function that refers to a static instance |
|
162 |
|
163 // the following optimization - inhibiting explicit instantiation for abstract |
|
164 // classes breaks msvc compliles |
|
165 template<class T, class ASeq> |
|
166 struct export_instance { |
|
167 struct abstract { |
|
168 static const export_generator<T, ASeq> * |
|
169 invoke(){ |
|
170 return 0; |
|
171 } |
|
172 }; |
|
173 struct not_abstract { |
|
174 static const export_generator<T, ASeq> * |
|
175 invoke(){ |
|
176 return & export_generator<T, ASeq>::instance; |
|
177 } |
|
178 }; |
|
179 }; |
|
180 |
|
181 template<class T, class ASeq> |
|
182 BOOST_DLLEXPORT |
|
183 std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *> |
|
184 export_instance_invoke() { |
|
185 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< |
|
186 serialization::is_abstract<T>, |
|
187 mpl::identity<BOOST_DEDUCED_TYPENAME export_instance<T, ASeq>::abstract>, |
|
188 mpl::identity<BOOST_DEDUCED_TYPENAME export_instance<T, ASeq>::not_abstract> |
|
189 >::type typex; |
|
190 return std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *>( |
|
191 typex::invoke(), |
|
192 & guid_initializer<T>::instance |
|
193 ); |
|
194 } |
|
195 |
|
196 template<class T, class ASeq> |
|
197 struct export_archives { |
|
198 struct empty_archive_list { |
|
199 static BOOST_DLLEXPORT |
|
200 std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *> |
|
201 invoke(){ |
|
202 return std::pair<const export_generator<T, ASeq> *, |
|
203 const guid_initializer<T> *>(0, 0); |
|
204 } |
|
205 }; |
|
206 struct non_empty_archive_list { |
|
207 static BOOST_DLLEXPORT |
|
208 std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *> |
|
209 invoke(){ |
|
210 return export_instance_invoke<T, ASeq>(); |
|
211 } |
|
212 }; |
|
213 }; |
|
214 |
|
215 template<class T, class ASeq> |
|
216 BOOST_DLLEXPORT |
|
217 std::pair<const export_generator<T, ASeq> *, const guid_initializer<T> *> |
|
218 export_archives_invoke(T &, ASeq &){ |
|
219 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< |
|
220 mpl::empty<ASeq>, |
|
221 mpl::identity<BOOST_DEDUCED_TYPENAME export_archives<T, ASeq>::empty_archive_list>, |
|
222 mpl::identity<BOOST_DEDUCED_TYPENAME export_archives<T, ASeq>::non_empty_archive_list> |
|
223 >::type typex; |
|
224 return typex::invoke(); |
|
225 } |
|
226 |
|
227 } // namespace detail |
|
228 } // namespace archive |
|
229 } // namespace boost |
|
230 |
|
231 #define BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, K, ASEQ) \ |
|
232 namespace boost { \ |
|
233 namespace archive { \ |
|
234 namespace detail { \ |
|
235 template<> \ |
|
236 const guid_initializer< T > \ |
|
237 guid_initializer< T >::instance(K); \ |
|
238 template \ |
|
239 BOOST_DLLEXPORT \ |
|
240 std::pair<const export_generator<T, ASEQ> *, const guid_initializer< T > *> \ |
|
241 export_archives_invoke<T, ASEQ>(T &, ASEQ &); \ |
|
242 } } } \ |
|
243 /**/ |
|
244 |
|
245 #endif |
|
246 |
|
247 // check for unnecessary export. T isn't polymorphic so there is no |
|
248 // need to export it. |
|
249 #define BOOST_CLASS_EXPORT_CHECK(T) \ |
|
250 BOOST_STATIC_WARNING( \ |
|
251 boost::serialization::type_info_implementation< T > \ |
|
252 ::type::is_polymorphic::value \ |
|
253 ); \ |
|
254 /**/ |
|
255 |
|
256 // the default list of archives types for which code id generated |
|
257 #define BOOST_CLASS_EXPORT_GUID(T, K) \ |
|
258 BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST( \ |
|
259 T, \ |
|
260 K, \ |
|
261 boost::archive::detail::known_archive_types::type \ |
|
262 ) \ |
|
263 /**/ |
|
264 |
|
265 // the default exportable class identifier is the class name |
|
266 #define BOOST_CLASS_EXPORT_ARCHIVE_LIST(T, ASEQ) \ |
|
267 BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST(T, BOOST_PP_STRINGIZE(T), A) |
|
268 |
|
269 // the default exportable class identifier is the class name |
|
270 // the default list of archives types for which code id generated |
|
271 // are the originally included with this serialization system |
|
272 #define BOOST_CLASS_EXPORT(T) \ |
|
273 BOOST_CLASS_EXPORT_GUID_ARCHIVE_LIST( \ |
|
274 T, \ |
|
275 BOOST_PP_STRINGIZE(T), \ |
|
276 boost::archive::detail::known_archive_types::type \ |
|
277 ) \ |
|
278 /**/ |
|
279 |
|
280 #endif // BOOST_SERIALIZATION_EXPORT_HPP |