|
1 #ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP |
|
2 #define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP |
|
3 |
|
4 // MS compatible compilers support #pragma once |
|
5 #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|
6 # pragma once |
|
7 #pragma inline_depth(511) |
|
8 #pragma inline_recursion(on) |
|
9 #endif |
|
10 |
|
11 #if defined(__MWERKS__) |
|
12 #pragma inline_depth(511) |
|
13 #endif |
|
14 |
|
15 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 |
|
16 // iserializer.hpp: interface for serialization system. |
|
17 |
|
18 // (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . |
|
19 // Use, modification and distribution is subject to the Boost Software |
|
20 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
|
21 // http://www.boost.org/LICENSE_1_0.txt) |
|
22 |
|
23 // See http://www.boost.org for updates, documentation, and revision history. |
|
24 |
|
25 #include <new> // for placement new |
|
26 #include <memory> // for auto_ptr |
|
27 #include <cstddef> // size_t |
|
28 |
|
29 #include <boost/config.hpp> |
|
30 #include <boost/detail/workaround.hpp> |
|
31 #if defined(BOOST_NO_STDC_NAMESPACE) |
|
32 namespace std{ |
|
33 using ::size_t; |
|
34 } // namespace std |
|
35 #endif |
|
36 #include <boost/throw_exception.hpp> |
|
37 #include <boost/smart_cast.hpp> |
|
38 #include <boost/static_assert.hpp> |
|
39 #include <boost/static_warning.hpp> |
|
40 #include <boost/detail/no_exceptions_support.hpp> |
|
41 |
|
42 #include <boost/type_traits/is_pointer.hpp> |
|
43 #include <boost/type_traits/is_fundamental.hpp> |
|
44 #include <boost/type_traits/is_enum.hpp> |
|
45 #include <boost/type_traits/is_const.hpp> |
|
46 #include <boost/type_traits/remove_const.hpp> |
|
47 #include <boost/serialization/is_abstract.hpp> |
|
48 |
|
49 #include <boost/mpl/eval_if.hpp> |
|
50 #include <boost/mpl/if.hpp> |
|
51 #include <boost/mpl/identity.hpp> |
|
52 #include <boost/mpl/or.hpp> |
|
53 #include <boost/mpl/and.hpp> |
|
54 #include <boost/mpl/less.hpp> |
|
55 #include <boost/mpl/greater_equal.hpp> |
|
56 #include <boost/mpl/int.hpp> |
|
57 #include <boost/mpl/list.hpp> |
|
58 #include <boost/mpl/empty.hpp> |
|
59 #include <boost/mpl/not.hpp> |
|
60 |
|
61 #ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO |
|
62 #include <boost/serialization/extended_type_info_typeid.hpp> |
|
63 #endif |
|
64 // the following is need only for dynamic cast of polymorphic pointers |
|
65 #include <boost/archive/detail/basic_iarchive.hpp> |
|
66 #include <boost/archive/detail/basic_iserializer.hpp> |
|
67 #include <boost/archive/detail/archive_pointer_iserializer.hpp> |
|
68 #include <boost/archive/archive_exception.hpp> |
|
69 |
|
70 #include <boost/serialization/force_include.hpp> |
|
71 #include <boost/serialization/serialization.hpp> |
|
72 #include <boost/serialization/version.hpp> |
|
73 #include <boost/serialization/level.hpp> |
|
74 #include <boost/serialization/tracking.hpp> |
|
75 #include <boost/serialization/type_info_implementation.hpp> |
|
76 #include <boost/serialization/nvp.hpp> |
|
77 #include <boost/serialization/binary_object.hpp> |
|
78 #include <boost/serialization/void_cast.hpp> |
|
79 |
|
80 namespace boost { |
|
81 |
|
82 namespace serialization { |
|
83 class extended_type_info; |
|
84 } // namespace serialization |
|
85 |
|
86 namespace archive { |
|
87 |
|
88 // an accessor to permit friend access to archives. Needed because |
|
89 // some compilers don't handle friend templates completely |
|
90 class load_access { |
|
91 public: |
|
92 template<class Archive, class T> |
|
93 static void load_primitive(Archive &ar, T &t){ |
|
94 ar.load(t); |
|
95 } |
|
96 }; |
|
97 |
|
98 namespace detail { |
|
99 |
|
100 template<class Archive, class T> |
|
101 class iserializer : public basic_iserializer |
|
102 { |
|
103 private: |
|
104 virtual void destroy(/*const*/ void *address) const { |
|
105 boost::serialization::access::destroy(static_cast<T *>(address)); |
|
106 } |
|
107 // private constructor to inhibit any existence other than the |
|
108 // static one |
|
109 explicit iserializer() : |
|
110 basic_iserializer( |
|
111 * boost::serialization::type_info_implementation<T>::type::get_instance() |
|
112 ) |
|
113 {} |
|
114 public: |
|
115 virtual BOOST_DLLEXPORT void load_object_data( |
|
116 basic_iarchive & ar, |
|
117 void *x, |
|
118 const unsigned int file_version |
|
119 ) const BOOST_USED ; |
|
120 virtual bool class_info() const { |
|
121 return boost::serialization::implementation_level<T>::value |
|
122 >= boost::serialization::object_class_info; |
|
123 } |
|
124 virtual bool tracking(const unsigned int flags) const { |
|
125 // if(0 != (flags & no_tracking)) |
|
126 // return false; |
|
127 return boost::serialization::tracking_level<T>::value |
|
128 == boost::serialization::track_always |
|
129 || boost::serialization::tracking_level<T>::value |
|
130 == boost::serialization::track_selectivly |
|
131 && serialized_as_pointer(); |
|
132 } |
|
133 virtual unsigned int version() const { |
|
134 return ::boost::serialization::version<T>::value; |
|
135 } |
|
136 virtual bool is_polymorphic() const { |
|
137 typedef BOOST_DEDUCED_TYPENAME |
|
138 boost::serialization::type_info_implementation< |
|
139 T |
|
140 >::type::is_polymorphic::type typex; |
|
141 return typex::value; |
|
142 } |
|
143 static iserializer & instantiate(){ |
|
144 static iserializer instance; |
|
145 return instance; |
|
146 } |
|
147 virtual ~iserializer(){}; |
|
148 }; |
|
149 |
|
150 template<class Archive, class T> |
|
151 BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data( |
|
152 basic_iarchive & ar, |
|
153 void *x, |
|
154 const unsigned int file_version |
|
155 ) const { |
|
156 // make sure call is routed through the higest interface that might |
|
157 // be specialized by the user. |
|
158 boost::serialization::serialize_adl( |
|
159 boost::smart_cast_reference<Archive &>(ar), |
|
160 * static_cast<T *>(x), |
|
161 file_version |
|
162 ); |
|
163 } |
|
164 |
|
165 // instantiation of this template creates a static object. Note inversion of |
|
166 // normal argument order to workaround bizarre error in MSVC 6.0 which only |
|
167 // manifests iftself during compiler time. |
|
168 template<class T, class Archive> |
|
169 class pointer_iserializer : public archive_pointer_iserializer<Archive> |
|
170 { |
|
171 private: |
|
172 virtual const basic_iserializer & get_basic_serializer() const { |
|
173 return iserializer<Archive, T>::instantiate(); |
|
174 } |
|
175 virtual BOOST_DLLEXPORT void load_object_ptr( |
|
176 basic_iarchive & ar, |
|
177 void * & x, |
|
178 const unsigned int file_version |
|
179 ) const BOOST_USED; |
|
180 #if defined(__GNUC__) || ( defined(BOOST_MSVC) && (_MSC_VER <= 1300) ) |
|
181 public: |
|
182 #endif |
|
183 // private constructor to inhibit any existence other than the |
|
184 // static one. Note GCC doesn't permit constructor to be private |
|
185 explicit BOOST_DLLEXPORT pointer_iserializer() BOOST_USED; |
|
186 static const pointer_iserializer instance; |
|
187 public: |
|
188 // at least one compiler (CW) seems to require that serialize_adl |
|
189 // be explicitly instantiated. Still under investigation. |
|
190 #if ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) |
|
191 void (* const m)(Archive &, T &, const unsigned); |
|
192 boost::serialization::extended_type_info * (* e)(); |
|
193 #endif |
|
194 static BOOST_DLLEXPORT const pointer_iserializer & instantiate() BOOST_USED; |
|
195 virtual ~pointer_iserializer(){}; |
|
196 }; |
|
197 |
|
198 template<class T, class Archive> |
|
199 BOOST_DLLEXPORT const pointer_iserializer<T, Archive> & |
|
200 pointer_iserializer<T, Archive>::instantiate() { |
|
201 return instance; |
|
202 } |
|
203 |
|
204 // note: instances of this template to be constructed before the main |
|
205 // is called in order for things to be initialized properly. For this |
|
206 // reason, hiding the instance in a static function as was done above |
|
207 // won't work here so we created a free instance here. |
|
208 template<class T, class Archive> |
|
209 const pointer_iserializer<T, Archive> pointer_iserializer<T, Archive>::instance; |
|
210 |
|
211 // note trick to be sure that operator new is using class specific |
|
212 // version if such exists. Due to Peter Dimov. |
|
213 // note: the following fails if T has no default constructor. |
|
214 // otherwise it would have been ideal |
|
215 //struct heap_allocator : public T |
|
216 //{ |
|
217 // T * invoke(){ |
|
218 // return ::new(sizeof(T)); |
|
219 // } |
|
220 //} |
|
221 |
|
222 // note: this should really be a member of the load_ptr function |
|
223 // below but some compilers still complain about this. |
|
224 template<class T> |
|
225 struct heap_allocator |
|
226 { |
|
227 #if 0 |
|
228 // note: this fails on msvc 7.0 and gcc 3.2 |
|
229 template <class U, U x> struct test; |
|
230 typedef char* yes; |
|
231 typedef int* no; |
|
232 template <class U> |
|
233 yes has_op_new(U*, test<void* (*)(std::size_t), &U::operator new>* = 0); |
|
234 no has_op_new(...); |
|
235 |
|
236 template<class U> |
|
237 T * new_operator(U); |
|
238 |
|
239 T * new_operator(yes){ |
|
240 return (T::operator new)(sizeof(T)); |
|
241 } |
|
242 T * new_operator(no){ |
|
243 return static_cast<T *>(operator new(sizeof(T))); |
|
244 } |
|
245 static T * invoke(){ |
|
246 return new_operator(has_op_new(static_cast<T *>(NULL))); |
|
247 } |
|
248 #else |
|
249 // while this doesn't handle operator new overload for class T |
|
250 static T * invoke(){ |
|
251 return static_cast<T *>(operator new(sizeof(T))); |
|
252 } |
|
253 #endif |
|
254 }; |
|
255 |
|
256 // due to Martin Ecker |
|
257 template <typename T> |
|
258 class auto_ptr_with_deleter |
|
259 { |
|
260 public: |
|
261 explicit auto_ptr_with_deleter(T* p) : |
|
262 m_p(p) |
|
263 {} |
|
264 ~auto_ptr_with_deleter(){ |
|
265 if (m_p) |
|
266 boost::serialization::access::destroy(m_p); |
|
267 } |
|
268 T* get() const { |
|
269 return m_p; |
|
270 } |
|
271 |
|
272 T* release() { |
|
273 T* p = m_p; |
|
274 m_p = NULL; |
|
275 return p; |
|
276 } |
|
277 private: |
|
278 T* m_p; |
|
279 }; |
|
280 |
|
281 template<class T, class Archive> |
|
282 BOOST_DLLEXPORT void pointer_iserializer<T, Archive>::load_object_ptr( |
|
283 basic_iarchive & ar, |
|
284 void * & x, |
|
285 const unsigned int file_version |
|
286 ) const { |
|
287 Archive & ar_impl = boost::smart_cast_reference<Archive &>(ar); |
|
288 |
|
289 // if(0 != (ar.get_flags() & no_object_creation)){ |
|
290 // ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(x)); |
|
291 // return; |
|
292 // } |
|
293 |
|
294 auto_ptr_with_deleter<T> ap(heap_allocator<T>::invoke()); |
|
295 if(NULL == ap.get()) |
|
296 boost::throw_exception(std::bad_alloc()) ; |
|
297 |
|
298 T * t = ap.get(); |
|
299 x = t; |
|
300 |
|
301 // catch exception during load_construct_data so that we don't |
|
302 // automatically delete the t which is most likely not fully |
|
303 // constructed |
|
304 BOOST_TRY { |
|
305 // this addresses an obscure situtation that occurs when |
|
306 // load_constructor de-serializes something through a pointer. |
|
307 ar.next_object_pointer(t); |
|
308 boost::serialization::load_construct_data_adl<Archive, T>( |
|
309 ar_impl, |
|
310 t, |
|
311 file_version |
|
312 ); |
|
313 } |
|
314 BOOST_CATCH(...){ |
|
315 BOOST_RETHROW; |
|
316 } |
|
317 BOOST_CATCH_END |
|
318 |
|
319 ar_impl >> boost::serialization::make_nvp(NULL, * t); |
|
320 ap.release(); |
|
321 } |
|
322 |
|
323 template<class T, class Archive> |
|
324 #if ! BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) |
|
325 BOOST_DLLEXPORT pointer_iserializer<T, Archive>::pointer_iserializer() : |
|
326 archive_pointer_iserializer<Archive>( |
|
327 * boost::serialization::type_info_implementation<T>::type::get_instance() |
|
328 ), |
|
329 m(boost::serialization::serialize_adl<Archive, T>), |
|
330 e(boost::serialization::type_info_implementation<T>::type::get_instance) |
|
331 #else |
|
332 BOOST_DLLEXPORT pointer_iserializer<T, Archive>::pointer_iserializer() : |
|
333 archive_pointer_iserializer<Archive>( |
|
334 * boost::serialization::type_info_implementation<T>::type::get_instance() |
|
335 ) |
|
336 #endif |
|
337 { |
|
338 iserializer<Archive, T> & bis = iserializer<Archive, T>::instantiate(); |
|
339 bis.set_bpis(this); |
|
340 } |
|
341 |
|
342 template<class Archive, class T> |
|
343 struct load_non_pointer_type { |
|
344 // note this bounces the call right back to the archive |
|
345 // with no runtime overhead |
|
346 struct load_primitive { |
|
347 static void invoke(Archive & ar, T & t){ |
|
348 load_access::load_primitive(ar, t); |
|
349 } |
|
350 }; |
|
351 // note this bounces the call right back to the archive |
|
352 // with no runtime overhead |
|
353 struct load_only { |
|
354 static void invoke(Archive & ar, T & t){ |
|
355 // short cut to user's serializer |
|
356 // make sure call is routed through the higest interface that might |
|
357 // be specialized by the user. |
|
358 boost::serialization::serialize_adl( |
|
359 ar, t, boost::serialization::version<T>::value |
|
360 ); |
|
361 } |
|
362 }; |
|
363 |
|
364 // note this save class information including version |
|
365 // and serialization level to the archive |
|
366 struct load_standard { |
|
367 static void invoke(Archive &ar, T &t){ |
|
368 //BOOST_STATIC_ASSERT(! boost::is_const<T>::value); |
|
369 // borland - for some reason T is const here - even though |
|
370 // its not called that way - so fix it her |
|
371 typedef BOOST_DEDUCED_TYPENAME boost::remove_const<T>::type typex; |
|
372 void * x = & const_cast<typex &>(t); |
|
373 ar.load_object(x, iserializer<Archive, T>::instantiate()); |
|
374 } |
|
375 }; |
|
376 |
|
377 struct load_conditional { |
|
378 static void invoke(Archive &ar, T &t){ |
|
379 //if(0 == (ar.get_flags() & no_tracking)) |
|
380 load_standard::invoke(ar, t); |
|
381 //else |
|
382 // load_only::invoke(ar, t); |
|
383 } |
|
384 }; |
|
385 |
|
386 typedef BOOST_DEDUCED_TYPENAME mpl::eval_if< |
|
387 // if its primitive |
|
388 mpl::equal_to< |
|
389 boost::serialization::implementation_level<T>, |
|
390 mpl::int_<boost::serialization::primitive_type> |
|
391 >, |
|
392 mpl::identity<load_primitive>, |
|
393 // else |
|
394 BOOST_DEDUCED_TYPENAME mpl::eval_if< |
|
395 // class info / version |
|
396 mpl::greater_equal< |
|
397 boost::serialization::implementation_level<T>, |
|
398 mpl::int_<boost::serialization::object_class_info> |
|
399 >, |
|
400 // do standard load |
|
401 mpl::identity<load_standard>, |
|
402 // else |
|
403 BOOST_DEDUCED_TYPENAME mpl::eval_if< |
|
404 // no tracking |
|
405 mpl::equal_to< |
|
406 boost::serialization::tracking_level<T>, |
|
407 mpl::int_<boost::serialization::track_never> |
|
408 >, |
|
409 // do a fast load |
|
410 mpl::identity<load_only>, |
|
411 // else |
|
412 // do a fast load only tracking is turned off |
|
413 mpl::identity<load_conditional> |
|
414 > > >::type typex; |
|
415 |
|
416 static void invoke(Archive & ar, T &t){ |
|
417 BOOST_STATIC_ASSERT(( |
|
418 mpl::greater_equal< |
|
419 boost::serialization::implementation_level<T>, |
|
420 mpl::int_<boost::serialization::primitive_type> |
|
421 >::value |
|
422 )); |
|
423 typex::invoke(ar, t); |
|
424 } |
|
425 }; |
|
426 |
|
427 template<class Archive, class Tptr> |
|
428 struct load_pointer_type { |
|
429 template<class T> |
|
430 struct abstract |
|
431 { |
|
432 static const basic_pointer_iserializer * register_type(Archive & /* ar */){ |
|
433 #if ! defined(__BORLANDC__) |
|
434 typedef BOOST_DEDUCED_TYPENAME |
|
435 boost::serialization::type_info_implementation<T>::type::is_polymorphic typex; |
|
436 // it has? to be polymorphic |
|
437 BOOST_STATIC_ASSERT(typex::value); |
|
438 #endif |
|
439 return static_cast<basic_pointer_iserializer *>(NULL); |
|
440 } |
|
441 }; |
|
442 |
|
443 template<class T> |
|
444 struct non_abstract |
|
445 { |
|
446 static const basic_pointer_iserializer * register_type(Archive & ar){ |
|
447 return ar.register_type(static_cast<T *>(NULL)); |
|
448 } |
|
449 }; |
|
450 |
|
451 template<class T> |
|
452 static const basic_pointer_iserializer * register_type(Archive &ar, T & /*t*/){ |
|
453 // there should never be any need to load an abstract polymorphic |
|
454 // class pointer. Inhibiting code generation for this |
|
455 // permits abstract base classes to be used - note: exception |
|
456 // virtual serialize functions used for plug-ins |
|
457 typedef BOOST_DEDUCED_TYPENAME |
|
458 mpl::eval_if< |
|
459 serialization::is_abstract<T>, |
|
460 mpl::identity<abstract<T> >, |
|
461 mpl::identity<non_abstract<T> > |
|
462 >::type typex; |
|
463 return typex::register_type(ar); |
|
464 } |
|
465 |
|
466 template<class T> |
|
467 static T * pointer_tweak( |
|
468 const boost::serialization::extended_type_info & eti, |
|
469 void * t, |
|
470 T & |
|
471 ) { |
|
472 // tweak the pointer back to the base class |
|
473 return static_cast<T *>( |
|
474 boost::serialization::void_upcast( |
|
475 eti, |
|
476 * boost::serialization::type_info_implementation<T>::type::get_instance(), |
|
477 t |
|
478 ) |
|
479 ); |
|
480 } |
|
481 |
|
482 static void invoke(Archive & ar, Tptr & t){ |
|
483 const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t); |
|
484 const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer( |
|
485 * reinterpret_cast<void **>(&t), |
|
486 bpis_ptr, |
|
487 archive_pointer_iserializer<Archive>::find |
|
488 ); |
|
489 // if the pointer isn't that of the base class |
|
490 if(newbpis_ptr != bpis_ptr){ |
|
491 t = pointer_tweak(newbpis_ptr->get_eti(), t, *t); |
|
492 } |
|
493 } |
|
494 }; |
|
495 |
|
496 template<class Archive, class T> |
|
497 struct load_enum_type { |
|
498 static void invoke(Archive &ar, T &t){ |
|
499 // convert integers to correct enum to load |
|
500 int i; |
|
501 ar >> boost::serialization::make_nvp(NULL, i); |
|
502 t = static_cast<T>(i); |
|
503 } |
|
504 }; |
|
505 |
|
506 template<class Archive, class T> |
|
507 struct load_array_type { |
|
508 static void invoke(Archive &ar, T &t){ |
|
509 // convert integers to correct enum to load |
|
510 int current_count = sizeof(t) / ( |
|
511 static_cast<char *>(static_cast<void *>(&t[1])) |
|
512 - static_cast<char *>(static_cast<void *>(&t[0])) |
|
513 ); |
|
514 int count; |
|
515 ar >> BOOST_SERIALIZATION_NVP(count); |
|
516 if(count > current_count) |
|
517 boost::throw_exception(archive::archive_exception( |
|
518 boost::archive::archive_exception::array_size_too_short |
|
519 )); |
|
520 int i; |
|
521 for(i = 0; i < count; ++i) |
|
522 ar >> boost::serialization::make_nvp("item", t[i]); |
|
523 } |
|
524 }; |
|
525 |
|
526 // note bogus arguments to workaround msvc 6 silent runtime failure |
|
527 template<class Archive, class T> |
|
528 BOOST_DLLEXPORT |
|
529 inline const basic_pointer_iserializer & |
|
530 instantiate_pointer_iserializer( |
|
531 Archive * /* ar = NULL */, |
|
532 T * /* t = NULL */ |
|
533 ) BOOST_USED; |
|
534 |
|
535 template<class Archive, class T> |
|
536 BOOST_DLLEXPORT |
|
537 inline const basic_pointer_iserializer & |
|
538 instantiate_pointer_iserializer( |
|
539 Archive * /* ar = NULL */, |
|
540 T * /* t = NULL */ |
|
541 ){ |
|
542 // note: reversal of order of arguments to work around msvc 6.0 bug |
|
543 // that manifests itself while trying to link. |
|
544 return pointer_iserializer<T, Archive>::instantiate(); |
|
545 } |
|
546 |
|
547 } // detail |
|
548 |
|
549 template<class Archive, class T> |
|
550 inline void load(Archive &ar, T &t){ |
|
551 // if this assertion trips. It means we're trying to load a |
|
552 // const object with a compiler that doesn't have correct |
|
553 // funtion template ordering. On other compilers, this is |
|
554 // handled below. |
|
555 BOOST_STATIC_ASSERT(! boost::is_const<T>::value); |
|
556 typedef |
|
557 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer<T>, |
|
558 mpl::identity<detail::load_pointer_type<Archive, T> > |
|
559 ,//else |
|
560 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array<T>, |
|
561 mpl::identity<detail::load_array_type<Archive, T> > |
|
562 ,//else |
|
563 BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum<T>, |
|
564 mpl::identity<detail::load_enum_type<Archive, T> > |
|
565 ,//else |
|
566 mpl::identity<detail::load_non_pointer_type<Archive, T> > |
|
567 > |
|
568 > |
|
569 >::type typex; |
|
570 typex::invoke(ar, t); |
|
571 } |
|
572 |
|
573 // BORLAND |
|
574 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560)) |
|
575 // borland has a couple fo problems |
|
576 // a) if function is partiall specialized - see below |
|
577 // const paramters are transformed to non-const ones |
|
578 // b) implementation of base_object can't be made to work |
|
579 // correctly which results in all base_object s being const. |
|
580 // So, strip off the const for borland. This breaks the trap |
|
581 // for loading const objects - but I see no alternative |
|
582 template<class Archive, class T> |
|
583 inline void load(Archive &ar, const T & t){ |
|
584 load(ar, const_cast<T &>(t)); |
|
585 } |
|
586 #endif |
|
587 |
|
588 // let wrappers through. (Someday implement is_wrapper) |
|
589 #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING |
|
590 template<class Archive, class T> |
|
591 inline void load(Archive &ar, const serialization::nvp<T> &t){ |
|
592 boost::archive::load(ar, const_cast<serialization::nvp<T> &>(t)); |
|
593 } |
|
594 template<class Archive> |
|
595 inline void load(Archive &ar, const serialization::binary_object &t){ |
|
596 boost::archive::load(ar, const_cast<serialization::binary_object &>(t)); |
|
597 } |
|
598 |
|
599 //template<class Archive, class T> |
|
600 //inline void load(Archive &ar, const serialization::binary_object &t){ |
|
601 // load(ar, const_cast<binary_object &>(t)); |
|
602 //} |
|
603 #endif |
|
604 |
|
605 } // namespace archive |
|
606 } // namespace boost |
|
607 |
|
608 #endif // BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP |