Line data Source code
1 : /*! \file cereal.hpp
2 : \brief Main cereal functionality */
3 : /*
4 : Copyright (c) 2014, Randolph Voorhies, Shane Grant
5 : All rights reserved.
6 :
7 : Redistribution and use in source and binary forms, with or without
8 : modification, are permitted provided that the following conditions are met:
9 : * Redistributions of source code must retain the above copyright
10 : notice, this list of conditions and the following disclaimer.
11 : * Redistributions in binary form must reproduce the above copyright
12 : notice, this list of conditions and the following disclaimer in the
13 : documentation and/or other materials provided with the distribution.
14 : * Neither the name of cereal nor the
15 : names of its contributors may be used to endorse or promote products
16 : derived from this software without specific prior written permission.
17 :
18 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 : ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 : WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 : DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
22 : DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 : (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 : LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 : ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 : SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 : */
29 : #ifndef CEREAL_CEREAL_HPP_
30 : #define CEREAL_CEREAL_HPP_
31 :
32 : #include <type_traits>
33 : #include <string>
34 : #include <memory>
35 : #include <functional>
36 : #include <unordered_map>
37 : #include <unordered_set>
38 : #include <vector>
39 : #include <cstddef>
40 : #include <cstdint>
41 : #include <functional>
42 :
43 : #include "cereal/macros.hpp"
44 : #include "cereal/details/traits.hpp"
45 : #include "cereal/details/helpers.hpp"
46 : #include "cereal/types/base_class.hpp"
47 :
48 : namespace cereal
49 : {
50 : // ######################################################################
51 : //! Creates a name value pair
52 : /*! @relates NameValuePair
53 : @ingroup Utility */
54 : template <class T> inline
55 5200 : NameValuePair<T> make_nvp( std::string const & name, T && value )
56 : {
57 5200 : return {name.c_str(), std::forward<T>(value)};
58 : }
59 800 :
60 : //! Creates a name value pair
61 800 : /*! @relates NameValuePair
62 : @ingroup Utility */
63 800 : template <class T> inline
64 : NameValuePair<T> make_nvp( const char * name, T && value )
65 800 : {
66 : return {name, std::forward<T>(value)};
67 800 : }
68 :
69 800 : //! Creates a name value pair for the variable T with the same name as the variable
70 : /*! @relates NameValuePair
71 2800 : @ingroup Utility */
72 : #define CEREAL_NVP(T) ::cereal::make_nvp(#T, T)
73 2800 :
74 : // ######################################################################
75 : //! Convenience function to create binary data for both const and non const pointers
76 : /*! @param data Pointer to beginning of the data
77 : @param size The size in bytes of the data
78 : @relates BinaryData
79 : @ingroup Utility */
80 2800 : template <class T> inline
81 574906 : BinaryData<T> binary_data( T && data, size_t size )
82 2800 : {
83 574906 : return {std::forward<T>(data), size};
84 1600 : }
85 285453 :
86 1600 : // ######################################################################
87 285453 : //! Creates a size tag from some variable.
88 1200 : /*! Will normally be used to serialize size (e.g. size()) information for
89 285453 : variable size containers. If you have a variable sized container,
90 1200 : the very first thing it serializes should be its size, wrapped in
91 285453 : a SizeTag.
92 :
93 400 : @relates SizeTag
94 : @ingroup Utility */
95 400 : template <class T> inline
96 72000 : SizeTag<T> make_size_tag( T && sz )
97 400 : {
98 72000 : return {std::forward<T>(sz)};
99 400 : }
100 36000 :
101 400 : // ######################################################################
102 36000 : //! Marks data for deferred serialization
103 400 : /*! cereal performs a recursive depth-first traversal of data it serializes. When
104 694106 : serializing smart pointers to large, nested, or cyclical data structures, it
105 400 : is possible to encounter a stack overflow from excessive recursion when following
106 694106 : a chain of pointers.
107 400 :
108 329053 : Deferment can help in these situations if the data can be serialized separately from
109 400 : the pointers used to traverse the structure. For example, a graph structure can have its
110 329053 : nodes serialized before its edges:
111 400 :
112 329053 : @code{.cpp}
113 400 : struct MyEdge
114 329053 : {
115 400 : std::shared_ptr<MyNode> connection;
116 : int some_value;
117 :
118 : template<class Archive>
119 232254 : void serialize(Archive & archive)
120 233054 : {
121 2301 : // when we serialize an edge, we'll defer serializing the associated node
122 11101 : archive( cereal::defer( connection ),
123 2700 : some_value );
124 11100 : }
125 14100 : };
126 16100 :
127 6268600 : struct MyGraphStructure
128 6273800 : {
129 3400 : std::vector<MyEdge> edges;
130 8600 : std::vector<MyNodes> nodes;
131 812300 :
132 815500 : template<class Archive>
133 5700 : void serialize(Archive & archive)
134 8900 : {
135 10896764 : // because of the deferment, we ensure all nodes are fully serialized
136 10899964 : // before any connection pointers to those nodes are serialized
137 64414 : archive( edges, nodes );
138 67614 :
139 82537 : // we have to explicitly inform the archive when it is safe to serialize
140 84137 : // the deferred data
141 84004 : archive.serializeDeferments();
142 85604 : }
143 65313 : };
144 66913 : @endcode
145 69305 :
146 69305 : @relates DeferredData
147 54299 : @ingroup Utility */
148 54299 : template <class T> inline
149 65604 : DeferredData<T> defer( T && value )
150 65604 : {
151 60937 : return {std::forward<T>(value)};
152 60937 : }
153 65204 :
154 65204 : // ######################################################################
155 589079 : //! Called before a type is serialized to set up any special archive state
156 589079 : //! for processing some type
157 65608 : /*! If designing a serializer that needs to set up any kind of special
158 65608 : state or output extra information for a type, specialize this function
159 70105 : for the archive type and the types that require the extra information.
160 70105 : @ingroup Internal */
161 79442 : template <class Archive, class T> inline
162 311696 : void prologue( Archive & /* archive */, T const & /* data */)
163 320413 : { }
164 90460 :
165 93418 : //! Called after a type is serialized to tear down any special archive state
166 85817 : //! for processing some type
167 75608 : /*! @ingroup Internal */
168 79008 : template <class Archive, class T> inline
169 103739 : void epilogue( Archive & /* archive */, T const & /* data */)
170 6369639 : { }
171 6347599 :
172 68499 : // ######################################################################
173 77803 : //! Special flags for archives
174 884603 : /*! AllowEmptyClassElision
175 880722 : This allows for empty classes to be serialized even if they do not provide
176 72522 : a serialization function. Classes with no data members are considered to be
177 154403 : empty. Be warned that if this is enabled and you attempt to serialize an
178 11047919 : empty class with improperly formed serialize or load/save functions, no
179 11140320 : static error will occur - the error will propogate silently and your
180 302516 : intended serialization functions may not be called. You can manually
181 233250 : ensure that your classes that have custom serialization are correct
182 250367 : by using the traits is_output_serializable and is_input_serializable
183 185402 : in cereal/details/traits.hpp.
184 184977 : @ingroup Internal */
185 336442 : enum Flags { AllowEmptyClassElision = 1 };
186 315748 :
187 407752 : // ######################################################################
188 410654 : //! Registers a specific Archive type with cereal
189 561554 : /*! This registration should be done once per archive. A good place to
190 551139 : put this is immediately following the definition of your archive.
191 195100 : Archive registration is only strictly necessary if you wish to
192 201507 : support pointers to polymorphic data types. All archives that
193 250209 : come with cereal are already registered.
194 246758 : @ingroup Internal */
195 998857 : #define CEREAL_REGISTER_ARCHIVE(Archive) \
196 1014708 : namespace cereal { namespace detail { \
197 209508 : template <class T, class BindingTag> \
198 714588 : typename polymorphic_serialization_support<Archive, T>::type \
199 776163 : instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \
200 259587 : } } /* end namespaces */
201 264810 :
202 278326 : //! Helper macro to omit unused warning
203 273827 : #if defined(__GNUC__)
204 273577 : // GCC / clang don't want the function
205 191177 : #define CEREAL_UNUSED_FUNCTION
206 199637 : #else
207 943975 : #define CEREAL_UNUSED_FUNCTION static void unused() { (void)version; }
208 938803 : #endif
209 140368 :
210 123317 : // ######################################################################
211 179312 : //! Defines a class version for some type
212 256372 : /*! Versioning information is optional and adds some small amount of
213 280172 : overhead to serialization. This overhead will occur both in terms of
214 203101 : space in the archive (the version information for each class will be
215 209001 : stored exactly once) as well as runtime (versioned serialization functions
216 216132 : must check to see if they need to load or store version information).
217 196132 :
218 235475 : Versioning is useful if you plan on fundamentally changing the way some
219 1036866 : type is serialized in the future. Versioned serialization functions
220 1071898 : cannot be used to load non-versioned data.
221 209776 :
222 300377 : By default, all types have an assumed version value of zero. By
223 361877 : using this macro, you may change the version number associated with
224 290444 : some type. cereal will then use this value as a second parameter
225 460144 : to your serialization functions.
226 877255 :
227 707155 : The interface for the serialization functions is nearly identical
228 373341 : to non-versioned serialization with the addition of a second parameter,
229 274106 : const std::uint32_t version, which will be supplied with the correct
230 389359 : version number. Serializing the version number on a save happens
231 488959 : automatically.
232 616600 :
233 540867 : Versioning cannot be mixed with non-versioned serialization functions.
234 4907808 : Having both types will result result in a compile time error. Data
235 4915142 : serialized without versioning cannot be loaded by a serialization
236 241049 : function with added versioning support.
237 429585 :
238 1992678 : Example interface for versioning on a non-member serialize function:
239 1844676 :
240 231582 : @code{cpp}
241 219275 : CEREAL_CLASS_VERSION( Mytype, 77 ); // register class version
242 277761 :
243 297265 : template <class Archive>
244 307276 : void serialize( Archive & ar, Mytype & t, const std::uint32_t version )
245 308045 : {
246 306345 : // When performing a load, the version associated with the class
247 277241 : // is whatever it was when that data was originally serialized
248 187341 : //
249 367252 : // When we save, we'll use the version that is defined in the macro
250 1604021 :
251 1433321 : if( version >= some_number )
252 142851 : // do this
253 121897 : else
254 199493 : // do that
255 244924 : }
256 255824 : @endcode
257 402305 :
258 398505 : Interfaces for other forms of serialization functions is similar. This
259 436867 : macro should be placed at global scope.
260 417667 : @ingroup Utility */
261 243908 : #define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \
262 1134904 : namespace cereal { namespace detail { \
263 1175028 : template <> struct Version<TYPE> \
264 220408 : { \
265 193276 : static const std::uint32_t version; \
266 786575 : static std::uint32_t registerVersion() \
267 718079 : { \
268 358779 : ::cereal::detail::StaticObject<Versions>::getInstance().mapping.emplace( \
269 1000877 : std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \
270 840277 : return VERSION_NUMBER; \
271 208362 : } \
272 112451 : CEREAL_UNUSED_FUNCTION \
273 146769 : }; /* end Version */ \
274 242289 : const std::uint32_t Version<TYPE>::version = \
275 406409 : Version<TYPE>::registerVersion(); \
276 397333 : } } // end namespaces
277 4920133 :
278 4931092 : // ######################################################################
279 199978 : //! The base output archive class
280 402089 : /*! This is the base output archive for all output archives. If you create
281 1287793 : a custom archive class, it should derive from this, passing itself as
282 1044298 : a template parameter for the ArchiveType.
283 171693 :
284 171991 : The base class provides all of the functionality necessary to
285 170923 : properly forward data to the correct serialization functions.
286 278808 :
287 433504 : Individual archives should use a combination of prologue and
288 338507 : epilogue functions together with specializations of serialize, save,
289 178047 : and load to alter the functionality of their serialization.
290 147741 :
291 150841 : @tparam ArchiveType The archive type that derives from OutputArchive
292 341949 : @tparam Flags Flags to control advanced functionality. See the Flags
293 1033831 : enum for more information.
294 2018032 : @ingroup Internal */
295 1325330 : template<class ArchiveType, std::uint32_t Flags = 0>
296 236501 : class OutputArchive : public detail::OutputArchiveBase
297 258522 : {
298 336693 : public:
299 405425 : //! Construct the output archive
300 517010 : /*! @param derived A pointer to the derived ArchiveType (pass this from the derived archive) */
301 507438 : OutputArchive(ArchiveType * const derived) : self(derived), itsCurrentPointerId(1), itsCurrentPolymorphicTypeId(1)
302 1272537 : { }
303 1189142 :
304 170942 : OutputArchive & operator=( OutputArchive const & ) = delete;
305 260440 :
306 433848 : //! Serializes all passed in data
307 423017 : /*! This is the primary interface for serializing data with an archive */
308 465401 : template <class ... Types> inline
309 1111632 : ArchiveType & operator()( Types && ... args )
310 1033038 : {
311 296005 : self->process( std::forward<Types>( args )... );
312 378803 : return *self;
313 466038 : }
314 1043341 :
315 991089 : //! Serializes any data marked for deferment
316 195290 : /*! This will cause any data wrapped in DeferredData to be immediately serialized
317 332015 : @relates defer */
318 615677 : void serializeDeferments()
319 626369 : {
320 406070 : for( auto & deferment : itsDeferments )
321 642969 : deferment();
322 644907 : }
323 320206 :
324 394903 : /*! @name Boost Transition Layer
325 350843 : Functionality that mirrors the syntax for Boost. This is useful if you are transitioning
326 1005540 : a large project from Boost to cereal. The preferred interface for cereal is using operator(). */
327 974107 : //! @{
328 168477 :
329 258470 : //! Indicates this archive is not intended for loading
330 495364 : /*! This ensures compatibility with boost archive types. If you are transitioning
331 411067 : from boost, you can check this value within a member or external serialize function
332 320686 : (i.e., Archive::is_loading::value) to disable behavior specific to loading, until
333 331713 : you can transition to split save/load or save_minimal/load_minimal functions */
334 420413 : using is_loading = std::false_type;
335 412149 :
336 449397 : //! Indicates this archive is intended for saving
337 1772127 : /*! This ensures compatibility with boost archive types. If you are transitioning
338 1492226 : from boost, you can check this value within a member or external serialize function
339 590836 : (i.e., Archive::is_saving::value) to enable behavior specific to loading, until
340 593186 : you can transition to split save/load or save_minimal/load_minimal functions */
341 324333 : using is_saving = std::true_type;
342 382758 :
343 291524 : //! Serializes passed in data
344 302876 : /*! This is a boost compatability layer and is not the preferred way of using
345 1028644 : cereal. If you are transitioning from boost, use this until you can
346 3451256 : transition to the operator() overload */
347 2663337 : template <class T> inline
348 196337 : ArchiveType & operator&( T && arg )
349 265068 : {
350 357804 : self->process( std::forward<T>( arg ) );
351 436898 : return *self;
352 541446 : }
353 511452 :
354 293027 : //! Serializes passed in data
355 216628 : /*! This is a boost compatability layer and is not the preferred way of using
356 285422 : cereal. If you are transitioning from boost, use this until you can
357 1011621 : transition to the operator() overload */
358 2168860 : template <class T> inline
359 1362560 : ArchiveType & operator<<( T && arg )
360 308000 : {
361 384900 : self->process( std::forward<T>( arg ) );
362 839793 : return *self;
363 800594 : }
364 545653 :
365 563551 : //! @}
366 2700802 :
367 2701904 : //! Registers a shared pointer with the archive
368 285154 : /*! This function is used to track shared pointer targets to prevent
369 1005154 : unnecessary saves from taking place if multiple shared pointers
370 1456557 : point to the same data.
371 648657 :
372 157162 : @internal
373 244261 : @param addr The address (see shared_ptr get()) pointed to by the shared pointer
374 243236 : @return A key that uniquely identifies the pointer */
375 315337 : inline std::uint32_t registerSharedPointer( void const * addr )
376 367493 : {
377 446893 : // Handle null pointers by just returning 0
378 400578 : if(addr == 0) return 0;
379 236977 :
380 407395 : auto id = itsSharedPointerMap.find( addr );
381 326994 : if( id == itsSharedPointerMap.end() )
382 492346 : {
383 490622 : auto ptrId = itsCurrentPointerId++;
384 123078 : itsSharedPointerMap.insert( {addr, ptrId} );
385 112802 : return ptrId | detail::msb_32bit; // mask MSB to be 1
386 110885 : }
387 111986 : else
388 133181 : return id->second;
389 2642581 : }
390 2652755 :
391 185955 : //! Registers a polymorphic type name with the archive
392 337434 : /*! This function is used to track polymorphic types to prevent
393 347733 : unnecessary saves of identifying strings used by the polymorphic
394 187290 : support functionality.
395 174890 :
396 134302 : @internal
397 164602 : @param name The name to associate with a polymorphic type
398 183121 : @return A key that uniquely identifies the polymorphic type name */
399 135321 : inline std::uint32_t registerPolymorphicType( char const * name )
400 116502 : {
401 1320149 : auto id = itsPolymorphicTypeMap.find( name );
402 1305949 : if( id == itsPolymorphicTypeMap.end() )
403 105903 : {
404 270303 : auto polyId = itsCurrentPolymorphicTypeId++;
405 779504 : itsPolymorphicTypeMap.insert( {name, polyId} );
406 595804 : return polyId | detail::msb_32bit; // mask MSB to be 1
407 117679 : }
408 124079 : else
409 2600402 : return id->second;
410 2684740 : }
411 230201 :
412 170849 : private:
413 643441 : //! Serializes data after calling prologue, then calls epilogue
414 608789 : template <class T> inline
415 217201 : void process( T && head )
416 543868 : {
417 779779 : prologue( *self, head );
418 440177 : self->processImpl( head );
419 135864 : epilogue( *self, head );
420 137966 : }
421 99003 :
422 97511 : //! Unwinds to process all data
423 107785 : template <class T, class ... Other> inline
424 266879 : void process( T && head, Other && ... tail )
425 266199 : {
426 150086 : self->process( std::forward<T>( head ) );
427 131891 : self->process( std::forward<Other>( tail )... );
428 130097 : }
429 130461 :
430 103461 : //! Serialization of a virtual_base_class wrapper
431 123469 : /*! \sa virtual_base_class */
432 126641 : template <class T> inline
433 126153 : ArchiveType & processImpl(virtual_base_class<T> const & b)
434 108053 : {
435 277932 : traits::detail::base_class_id id(b.base_ptr);
436 275896 : if(itsBaseClassSet.count(id) == 0)
437 106528 : {
438 125550 : itsBaseClassSet.insert(id);
439 105134 : self->processImpl( *b.base_ptr );
440 134523 : }
441 152385 : return *self;
442 135287 : }
443 116929 :
444 117170 : //! Serialization of a base_class wrapper
445 102674 : /*! \sa base_class */
446 106674 : template <class T> inline
447 258970 : ArchiveType & processImpl(base_class<T> const & b)
448 289474 : {
449 125772 : self->processImpl( *b.base_ptr );
450 103859 : return *self;
451 103359 : }
452 125436 :
453 218656 : std::vector<std::function<void(void)>> itsDeferments;
454 201852 :
455 131820 : template <class T> inline
456 121820 : ArchiveType & processImpl(DeferredData<T> const & d)
457 87499 : {
458 219203 : std::function<void(void)> deferment( [=](){ self->process( d.value ); } );
459 575637 : itsDeferments.emplace_back( std::move(deferment) );
460 851449 :
461 451047 : return *self;
462 76002 : }
463 67606 :
464 55995 : //! Helper macro that expands the requirements for activating an overload
465 57101 : /*! Requirements:
466 410235 : Has the requested serialization function
467 227230 : Does not have version and unversioned at the same time
468 568306 : Is output serializable AND
469 454304 : is specialized for this type of function OR
470 3438194 : has no specialization at all */
471 3436870 : #define PROCESS_IF(name) \
472 133379 : traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \
473 105781 : !traits::has_invalid_output_versioning<T, ArchiveType>::value, \
474 105679 : (traits::is_output_serializable<T, ArchiveType>::value && \
475 106278 : (traits::is_specialized_##name<T, ArchiveType>::value || \
476 152797 : !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae
477 124895 :
478 95997 : //! Member serialization
479 93783 : template <class T, PROCESS_IF(member_serialize)> inline
480 87266 : ArchiveType & processImpl(T const & t)
481 116027 : {
482 3395914 : access::member_serialize(*self, const_cast<T &>(t));
483 96765 : return *self;
484 3404411 : }
485 3416214 :
486 399691 : //! Non member serialization
487 412013 : template <class T, PROCESS_IF(non_member_serialize)> inline
488 136475 : ArchiveType & processImpl(T const & t)
489 146386 : {
490 105017 : CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t));
491 133406 : return *self;
492 301532 : }
493 181333 :
494 205411 : //! Member split (save)
495 225902 : template <class T, PROCESS_IF(member_save)> inline
496 134737 : ArchiveType & processImpl(T const & t)
497 205132 : {
498 117060 : access::member_save(*self, t);
499 205753 : return *self;
500 364098 : }
501 316601 :
502 266599 : //! Non member split (save)
503 226918 : template <class T, PROCESS_IF(non_member_save)> inline
504 532174 : ArchiveType & processImpl(T const & t)
505 480886 : {
506 460572 : CEREAL_SAVE_FUNCTION_NAME(*self, t);
507 205344 : return *self;
508 450118 : }
509 885864 :
510 227073 : //! Member split (save_minimal)
511 476237 : template <class T, PROCESS_IF(member_save_minimal)> inline
512 539238 : ArchiveType & processImpl(T const & t)
513 3441289 : {
514 3550014 : self->process( access::member_save_minimal(*self, t) );
515 238675 : return *self;
516 140126 : }
517 134020 :
518 313427 : //! Non member split (save_minimal)
519 363782 : template <class T, PROCESS_IF(non_member_save_minimal)> inline
520 375869 : ArchiveType & processImpl(T const & t)
521 353269 : {
522 232396 : self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t) );
523 235041 : return *self;
524 483747 : }
525 3760003 :
526 148706 : //! Empty class specialization
527 3453850 : template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
528 3442958 : !traits::is_output_serializable<T, ArchiveType>::value,
529 427633 : std::is_empty<T>::value> = traits::sfinae> inline
530 435583 : ArchiveType & processImpl(T const &)
531 158032 : {
532 153937 : return *self;
533 153650 : }
534 217875 :
535 374141 : //! No matching serialization
536 409302 : /*! Invalid if we have invalid output versioning or
537 424526 : we are not output serializable, and either
538 634082 : don't allow empty class ellision or allow it but are not serializing an empty class */
539 149465 : template <class T, traits::EnableIf<traits::has_invalid_output_versioning<T, ArchiveType>::value ||
540 616502 : (!traits::is_output_serializable<T, ArchiveType>::value &&
541 537268 : (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
542 319904 : ArchiveType & processImpl(T const &)
543 476284 : {
544 315217 : static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value != 0,
545 235668 : "cereal could not find any output serialization functions for the provided type and archive combination. \n\n "
546 145270 : "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
547 512503 : "Serialize functions generally have the following signature: \n\n "
548 668823 : "template<class Archive> \n "
549 648721 : " void serialize(Archive & ar) \n "
550 244988 : " { \n "
551 488967 : " ar( member1, member2, member3 ); \n "
552 558843 : " } \n\n " );
553 251833 :
554 142847 : static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value < 2,
555 215447 : "cereal found more than one compatible output serialization function for the provided type and archive combination. \n\n "
556 125921 : "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
557 229677 : "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
558 218432 : "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
559 113416 : "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
560 126161 :
561 301664 : return *self;
562 296575 : }
563 328306 :
564 324115 : //! Registers a class version with the archive and serializes it if necessary
565 213443 : /*! If this is the first time this class has been serialized, we will record its
566 221999 : version number and serialize that.
567 451087 :
568 429940 : @tparam T The type of the class being serialized */
569 115674 : template <class T> inline
570 108903 : std::uint32_t registerClassVersion()
571 112308 : {
572 185504 : static const auto hash = std::type_index(typeid(T)).hash_code();
573 194831 : const auto insertResult = itsVersionedTypes.insert( hash );
574 143823 : const auto lock = detail::StaticObject<detail::Versions>::lock();
575 134726 : const auto version =
576 128982 : detail::StaticObject<detail::Versions>::getInstance().find( hash, detail::Version<T>::version );
577 183293 :
578 177448 : if( insertResult.second ) // insertion took place, serialize the version number
579 308373 : process( make_nvp<ArchiveType>("cereal_class_version", version) );
580 289424 :
581 499192 : return version;
582 108293 : }
583 485068 :
584 484663 : //! Member serialization
585 178871 : /*! Versioning implementation */
586 179869 : template <class T, PROCESS_IF(member_versioned_serialize)> inline
587 97106 : ArchiveType & processImpl(T const & t)
588 95108 : {
589 85203 : access::member_serialize(*self, const_cast<T &>(t), registerClassVersion<T>());
590 85024 : return *self;
591 252577 : }
592 233947 :
593 84672 : //! Non member serialization
594 85852 : /*! Versioning implementation */
595 74194 : template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
596 73130 : ArchiveType & processImpl(T const & t)
597 53701 : {
598 82843 : CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t), registerClassVersion<T>());
599 83601 : return *self;
600 66404 : }
601 73407 :
602 785361 : //! Member split (save)
603 87057 : /*! Versioning implementation */
604 821550 : template <class T, PROCESS_IF(member_versioned_save)> inline
605 792618 : ArchiveType & processImpl(T const & t)
606 76006 : {
607 45619 : access::member_save(*self, t, registerClassVersion<T>());
608 86718 : return *self;
609 85711 : }
610 45170 :
611 53262 : //! Non member split (save)
612 34016 : /*! Versioning implementation */
613 55756 : template <class T, PROCESS_IF(non_member_versioned_save)> inline
614 55454 : ArchiveType & processImpl(T const & t)
615 114109 : {
616 141680 : CEREAL_SAVE_FUNCTION_NAME(*self, t, registerClassVersion<T>());
617 63174 : return *self;
618 92960 : }
619 55359 :
620 53665 : //! Member split (save_minimal)
621 72672 : /*! Versioning implementation */
622 34959 : template <class T, PROCESS_IF(member_versioned_save_minimal)> inline
623 55057 : ArchiveType & processImpl(T const & t)
624 45554 : {
625 35806 : self->process( access::member_save_minimal(*self, t, registerClassVersion<T>()) );
626 55406 : return *self;
627 115603 : }
628 45206 :
629 136003 : //! Non member split (save_minimal)
630 116706 : /*! Versioning implementation */
631 59206 : template <class T, PROCESS_IF(non_member_versioned_save_minimal)> inline
632 204403 : ArchiveType & processImpl(T const & t)
633 59304 : {
634 238050 : self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t, registerClassVersion<T>()) );
635 198304 : return *self;
636 37751 : }
637 204652 :
638 41003 : #undef PROCESS_IF
639 213652 :
640 199605 : private:
641 58250 : ArchiveType * const self;
642 223550 :
643 49303 : //! A set of all base classes that have been serialized
644 243458 : std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
645 952007 :
646 61362 : //! Maps from addresses to pointer ids
647 960360 : std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap;
648 771904 :
649 225506 : //! The id to be given to the next pointer
650 205405 : std::uint32_t itsCurrentPointerId;
651 77005 :
652 227705 : //! Maps from polymorphic type name strings to ids
653 36504 : std::unordered_map<char const *, std::uint32_t> itsPolymorphicTypeMap;
654 336051 :
655 295603 : //! The id to be given to the next polymorphic type name
656 410250 : std::uint32_t itsCurrentPolymorphicTypeId;
657 374350 :
658 55003 : //! Keeps track of classes that have versioning information associated with them
659 85690 : std::unordered_set<size_type> itsVersionedTypes;
660 19190 : }; // class OutputArchive
661 74264 :
662 213005 : // ######################################################################
663 62364 : //! The base input archive class
664 261821 : /*! This is the base input archive for all input archives. If you create
665 194005 : a custom archive class, it should derive from this, passing itself as
666 74860 : a template parameter for the ArchiveType.
667 214658 :
668 64705 : The base class provides all of the functionality necessary to
669 264906 : properly forward data to the correct serialization functions.
670 284303 :
671 65006 : Individual archives should use a combination of prologue and
672 227704 : epilogue functions together with specializations of serialize, save,
673 234705 : and load to alter the functionality of their serialization.
674 416306 :
675 539803 : @tparam ArchiveType The archive type that derives from InputArchive
676 76104 : @tparam Flags Flags to control advanced functionality. See the Flags
677 323704 : enum for more information.
678 231402 : @ingroup Internal */
679 164303 : template<class ArchiveType, std::uint32_t Flags = 0>
680 302302 : class InputArchive : public detail::InputArchiveBase
681 47902 : {
682 318303 : public:
683 226002 : //! Construct the output archive
684 140804 : /*! @param derived A pointer to the derived ArchiveType (pass this from the derived archive) */
685 298202 : InputArchive(ArchiveType * const derived) :
686 70103 : self(derived),
687 312130 : itsBaseClassSet(),
688 242626 : itsSharedPointerMap(),
689 162630 : itsPolymorphicTypeMap(),
690 293828 : itsVersionedTypes()
691 68203 : { }
692 307305 :
693 247702 : InputArchive & operator=( InputArchive const & ) = delete;
694 174705 :
695 295803 : //! Serializes all passed in data
696 55803 : /*! This is the primary interface for serializing data with an archive */
697 505205 : template <class ... Types> inline
698 2153302 : ArchiveType & operator()( Types && ... args )
699 583252 : {
700 2392351 : process( std::forward<Types>( args )... );
701 1932402 : return *self;
702 72003 : }
703 61702 :
704 69204 : //! Serializes any data marked for deferment
705 228326 : /*! This will cause any data wrapped in DeferredData to be immediately serialized
706 84927 : @relates defer */
707 325029 : void serializeDeferments()
708 254726 : {
709 164605 : for( auto & deferment : itsDeferments )
710 632959 : deferment();
711 134503 : }
712 660961 :
713 571558 : /*! @name Boost Transition Layer
714 193605 : Functionality that mirrors the syntax for Boost. This is useful if you are transitioning
715 288972 : a large project from Boost to cereal. The preferred interface for cereal is using operator(). */
716 203303 : //! @{
717 515222 :
718 424195 : //! Indicates this archive is intended for loading
719 172980 : /*! This ensures compatibility with boost archive types. If you are transitioning
720 268153 : from boost, you can check this value within a member or external serialize function
721 119801 : (i.e., Archive::is_loading::value) to enable behavior specific to loading, until
722 1145585 : you can transition to split save/load or save_minimal/load_minimal functions */
723 184651 : using is_loading = std::true_type;
724 1063084 :
725 1186300 : //! Indicates this archive is not intended for saving
726 96212 : /*! This ensures compatibility with boost archive types. If you are transitioning
727 236598 : from boost, you can check this value within a member or external serialize function
728 169128 : (i.e., Archive::is_saving::value) to disable behavior specific to loading, until
729 157092 : you can transition to split save/load or save_minimal/load_minimal functions */
730 258392 : using is_saving = std::false_type;
731 106812 :
732 197837 : //! Serializes passed in data
733 187701 : /*! This is a boost compatability layer and is not the preferred way of using
734 76736 : cereal. If you are transitioning from boost, use this until you can
735 161369 : transition to the operator() overload */
736 76423 : template <class T> inline
737 250937 : ArchiveType & operator&( T && arg )
738 2015856 : {
739 173125 : self->process( std::forward<T>( arg ) );
740 2191504 : return *self;
741 3791623 : }
742 347062 :
743 2162958 : //! Serializes passed in data
744 2034006 : /*! This is a boost compatability layer and is not the preferred way of using
745 202123 : cereal. If you are transitioning from boost, use this until you can
746 498907 : transition to the operator() overload */
747 169821 : template <class T> inline
748 445818 : ArchiveType & operator>>( T && arg )
749 520801 : {
750 349135 : self->process( std::forward<T>( arg ) );
751 207803 : return *self;
752 573185 : }
753 851264 :
754 198200 : //! @}
755 583375 :
756 412881 : //! Retrieves a shared pointer given a unique key for it
757 266305 : /*! This is used to retrieve a previously registered shared_ptr
758 243054 : which has already been loaded.
759 193381 :
760 325149 : @internal
761 155364 : @param id The unique id that was serialized for the pointer
762 171978 : @return A shared pointer to the data
763 244694 : @throw Exception if the id does not exist */
764 102146 : inline std::shared_ptr<void> getSharedPointer(std::uint32_t const id)
765 1089662 : {
766 149377 : if(id == 0) return std::shared_ptr<void>(nullptr);
767 1053419 :
768 1146888 : auto iter = itsSharedPointerMap.find( id );
769 82154 : if(iter == itsSharedPointerMap.end())
770 198223 : throw Exception("Error while trying to deserialize a smart pointer. Could not find id " + std::to_string(id));
771 137472 :
772 147366 : return iter->second;
773 236651 : }
774 97515 :
775 150872 : //! Registers a shared pointer to its unique identifier
776 158014 : /*! After a shared pointer has been allocated for the first time, it should
777 88460 : be registered with its loaded id for future references to it.
778 100724 :
779 87189 : @internal
780 179987 : @param id The unique identifier for the shared pointer
781 1934067 : @param ptr The actual shared pointer */
782 147690 : inline void registerSharedPointer(std::uint32_t const id, std::shared_ptr<void> ptr)
783 2083012 : {
784 1920157 : std::uint32_t const stripped_id = id & ~detail::msb_32bit;
785 244287 : itsSharedPointerMap[stripped_id] = ptr;
786 164130 : }
787 187334 :
788 297492 : //! Retrieves the string for a polymorphic type given a unique key for it
789 511006 : /*! This is used to retrieve a string previously registered during
790 246802 : a polymorphic load.
791 469420 :
792 506985 : @internal
793 315847 : @param id The unique id that was serialized for the polymorphic type
794 226207 : @return The string identifier for the tyep */
795 592637 : inline std::string getPolymorphicName(std::uint32_t const id)
796 481344 : {
797 137097 : auto name = itsPolymorphicTypeMap.find( id );
798 217416 : if(name == itsPolymorphicTypeMap.end())
799 59907 : {
800 156423 : throw Exception("Error while trying to deserialize a polymorphic pointer. Could not find type id " + std::to_string(id));
801 113209 : }
802 125009 : return name->second;
803 235494 : }
804 85016 :
805 105642 : //! Registers a polymorphic name string to its unique identifier
806 145491 : /*! After a polymorphic type has been loaded for the first time, it should
807 55571 : be registered with its loaded id for future references to it.
808 125557 :
809 85408 : @internal
810 67279 : @param id The unique identifier for the polymorphic type
811 127386 : @param name The name associated with the tyep */
812 36902 : inline void registerPolymorphicName(std::uint32_t const id, std::string const & name)
813 135825 : {
814 598503 : std::uint32_t const stripped_id = id & ~detail::msb_32bit;
815 105713 : itsPolymorphicTypeMap.insert( {stripped_id, name} );
816 645937 : }
817 546609 :
818 626682 : private:
819 586519 : //! Serializes data after calling prologue, then calls epilogue
820 116203 : template <class T> inline
821 85377 : void process( T && head )
822 73727 : {
823 127791 : prologue( *self, head );
824 36107 : self->processImpl( head );
825 93186 : epilogue( *self, head );
826 144396 : }
827 34220 :
828 152200 : //! Unwinds to process all data
829 94609 : template <class T, class ... Other> inline
830 114553 : void process( T && head, Other && ... tail )
831 143983 : {
832 75578 : process( std::forward<T>( head ) );
833 125849 : process( std::forward<Other>( tail )... );
834 96109 : }
835 96287 :
836 104787 : //! Serialization of a virtual_base_class wrapper
837 115508 : /*! \sa virtual_base_class */
838 165307 : template <class T> inline
839 93803 : ArchiveType & processImpl(virtual_base_class<T> & b)
840 74808 : {
841 86491 : traits::detail::base_class_id id(b.base_ptr);
842 36100 : if(itsBaseClassSet.count(id) == 0)
843 85589 : {
844 83200 : itsBaseClassSet.insert(id);
845 74276 : self->processImpl( *b.base_ptr );
846 120208 : }
847 43826 : return *self;
848 120124 : }
849 120932 :
850 109413 : //! Serialization of a base_class wrapper
851 92614 : /*! \sa base_class */
852 51426 : template <class T> inline
853 73714 : ArchiveType & processImpl(base_class<T> & b)
854 66229 : {
855 64614 : self->processImpl( *b.base_ptr );
856 76215 : return *self;
857 27907 : }
858 85601 :
859 66915 : std::vector<std::function<void(void)>> itsDeferments;
860 5275176 :
861 77312 : template <class T> inline
862 5273595 : ArchiveType & processImpl(DeferredData<T> const & d)
863 5312838 : {
864 5283019 : std::function<void(void)> deferment( [=](){ self->process( d.value ); } );
865 5289468 : itsDeferments.emplace_back( std::move(deferment) );
866 84182 :
867 41601 : return *self;
868 92692 : }
869 74906 :
870 66824 : //! Helper macro that expands the requirements for activating an overload
871 74308 : /*! Requirements:
872 147023 : Has the requested serialization function
873 108196 : Does not have version and unversioned at the same time
874 173108 : Is input serializable AND
875 196715 : is specialized for this type of function OR
876 165386 : has no specialization at all */
877 171841 : #define PROCESS_IF(name) \
878 167041 : traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \
879 61707 : !traits::has_invalid_input_versioning<T, ArchiveType>::value, \
880 160477 : (traits::is_input_serializable<T, ArchiveType>::value && \
881 124806 : (traits::is_specialized_##name<T, ArchiveType>::value || \
882 157077 : !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae
883 164024 :
884 1013006 : //! Member serialization
885 66429 : template <class T, PROCESS_IF(member_serialize)> inline
886 993955 : ArchiveType & processImpl(T & t)
887 1003229 : {
888 1028831 : access::member_serialize(*self, t);
889 990207 : return *self;
890 50811 : }
891 24704 :
892 116718 : //! Non member serialization
893 69608 : template <class T, PROCESS_IF(non_member_serialize)> inline
894 102914 : ArchiveType & processImpl(T & t)
895 122099 : {
896 98506 : CEREAL_SERIALIZE_FUNCTION_NAME(*self, t);
897 127296 : return *self;
898 110892 : }
899 69665 :
900 77966 : //! Member split (load)
901 55407 : template <class T, PROCESS_IF(member_load)> inline
902 50611 : ArchiveType & processImpl(T & t)
903 51682 : {
904 71513 : access::member_load(*self, t);
905 90488 : return *self;
906 4762483 : }
907 65354 :
908 4790982 : //! Non member split (load)
909 4770154 : template <class T, PROCESS_IF(non_member_load)> inline
910 4790432 : ArchiveType & processImpl(T & t)
911 4760430 : {
912 55654 : CEREAL_LOAD_FUNCTION_NAME(*self, t);
913 64328 : return *self;
914 45605 : }
915 55027 :
916 35628 : //! Member split (load_minimal)
917 26407 : template <class T, PROCESS_IF(member_load_minimal)> inline
918 144675 : ArchiveType & processImpl(T & t)
919 26057 : {
920 127270 : using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
921 106321 : typename traits::has_member_save_minimal<T, OutArchiveType>::type value;
922 172789 : self->process( value );
923 132731 : access::member_load_minimal(*self, t, value);
924 151190 : return *self;
925 98319 : }
926 124381 :
927 162707 : //! Non member split (load_minimal)
928 135887 : template <class T, PROCESS_IF(non_member_load_minimal)> inline
929 144654 : ArchiveType & processImpl(T & t)
930 1025255 : {
931 23333 : using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
932 1018319 : typename traits::has_non_member_save_minimal<T, OutArchiveType>::type value;
933 983741 : self->process( value );
934 1002555 : CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value);
935 1043256 : return *self;
936 22025 : }
937 89640 :
938 63500 : //! Empty class specialization
939 59406 : template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
940 98171 : !traits::is_input_serializable<T, ArchiveType>::value,
941 57322 : std::is_empty<T>::value> = traits::sfinae> inline
942 86807 : ArchiveType & processImpl(T const &)
943 83408 : {
944 173056 : return *self;
945 103907 : }
946 2566558 :
947 126653 : //! No matching serialization
948 2598605 : /*! Invalid if we have invalid input versioning or
949 2528858 : we are not input serializable, and either
950 92503 : don't allow empty class ellision or allow it but are not serializing an empty class */
951 91308 : template <class T, traits::EnableIf<traits::has_invalid_input_versioning<T, ArchiveType>::value ||
952 57810 : (!traits::is_input_serializable<T, ArchiveType>::value &&
953 76155 : (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
954 55611 : ArchiveType & processImpl(T const &)
955 75709 : {
956 602154 : static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value != 0,
957 56906 : "cereal could not find any input serialization functions for the provided type and archive combination. \n\n "
958 614708 : "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
959 592158 : "Serialize functions generally have the following signature: \n\n "
960 593061 : "template<class Archive> \n "
961 581511 : " void serialize(Archive & ar) \n "
962 6605 : " { \n "
963 37212 : " ar( member1, member2, member3 ); \n "
964 26211 : " } \n\n " );
965 74786 :
966 47012 : static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value < 2,
967 74437 : "cereal found more than one compatible input serialization function for the provided type and archive combination. \n\n "
968 112886 : "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
969 37012 : "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
970 142991 : "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
971 53956 : "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
972 127236 :
973 153066 : return *self;
974 94604 : }
975 135684 :
976 106283 : //! Befriend for versioning in load_and_construct
977 79796 : template <class A, class B, bool C, bool D, bool E, bool F> friend struct detail::Construct;
978 188971 :
979 85644 : //! Registers a class version with the archive and serializes it if necessary
980 188374 : /*! If this is the first time this class has been serialized, we will record its
981 131168 : version number and serialize that.
982 118790 :
983 103420 : @tparam T The type of the class being serialized */
984 81924 : template <class T> inline
985 127324 : std::uint32_t loadClassVersion()
986 96239 : {
987 106414 : static const auto hash = std::type_index(typeid(T)).hash_code();
988 158315 : auto lookupResult = itsVersionedTypes.find( hash );
989 2474218 :
990 267424 : if( lookupResult != itsVersionedTypes.end() ) // already exists
991 2553222 : return lookupResult->second;
992 2632572 : else // need to load
993 296784 : {
994 204469 : std::uint32_t version;
995 166823 :
996 125493 : process( make_nvp<ArchiveType>("cereal_class_version", version) );
997 87903 : itsVersionedTypes.emplace_hint( lookupResult, hash, version );
998 137793 :
999 93190 : return version;
1000 86413 : }
1001 86058 : }
1002 641412 :
1003 107066 : //! Member serialization
1004 653064 : /*! Versioning implementation */
1005 651163 : template <class T, PROCESS_IF(member_versioned_serialize)> inline
1006 641368 : ArchiveType & processImpl(T & t)
1007 580983 : {
1008 86316 : const auto version = loadClassVersion<T>();
1009 74593 : access::member_serialize(*self, t, version);
1010 96492 : return *self;
1011 97311 : }
1012 56999 :
1013 108028 : //! Non member serialization
1014 87899 : /*! Versioning implementation */
1015 95123 : template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
1016 154835 : ArchiveType & processImpl(T & t)
1017 55747 : {
1018 185759 : const auto version = loadClassVersion<T>();
1019 105996 : CEREAL_SERIALIZE_FUNCTION_NAME(*self, t, version);
1020 176899 : return *self;
1021 205613 : }
1022 195204 :
1023 155625 : //! Member split (load)
1024 286604 : /*! Versioning implementation */
1025 226061 : template <class T, PROCESS_IF(member_versioned_load)> inline
1026 275121 : ArchiveType & processImpl(T & t)
1027 218694 : {
1028 539170 : const auto version = loadClassVersion<T>();
1029 109407 : access::member_load(*self, t, version);
1030 498320 : return *self;
1031 513487 : }
1032 452405 :
1033 592940 : //! Non member split (load)
1034 481651 : /*! Versioning implementation */
1035 142217 : template <class T, PROCESS_IF(non_member_versioned_load)> inline
1036 616086 : ArchiveType & processImpl(T & t)
1037 431842 : {
1038 552085 : const auto version = loadClassVersion<T>();
1039 510925 : CEREAL_LOAD_FUNCTION_NAME(*self, t, version);
1040 514681 : return *self;
1041 150629 : }
1042 526329 :
1043 512120 : //! Member split (load_minimal)
1044 564905 : /*! Versioning implementation */
1045 599221 : template <class T, PROCESS_IF(member_versioned_load_minimal)> inline
1046 132628 : ArchiveType & processImpl(T & t)
1047 123303 : {
1048 168114 : using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
1049 127010 : const auto version = loadClassVersion<T>();
1050 137893 : typename traits::has_member_versioned_save_minimal<T, OutArchiveType>::type value;
1051 126826 : self->process(value);
1052 67608 : access::member_load_minimal(*self, t, value, version);
1053 124798 : return *self;
1054 143742 : }
1055 81818 :
1056 164625 : //! Non member split (load_minimal)
1057 139889 : /*! Versioning implementation */
1058 319911 : template <class T, PROCESS_IF(non_member_versioned_load_minimal)> inline
1059 119908 : ArchiveType & processImpl(T & t)
1060 291298 : {
1061 310013 : using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
1062 235594 : const auto version = loadClassVersion<T>();
1063 356205 : typename traits::has_non_member_versioned_save_minimal<T, OutArchiveType>::type value;
1064 247803 : self->process(value);
1065 96998 : CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value, version);
1066 275113 : return *self;
1067 166009 : }
1068 374613 :
1069 225010 : #undef PROCESS_IF
1070 410803 :
1071 218205 : private:
1072 317083 : ArchiveType * const self;
1073 395109 :
1074 652696 : //! A set of all base classes that have been serialized
1075 281825 : std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
1076 662502 :
1077 437408 : //! Maps from pointer ids to metadata
1078 641818 : std::unordered_map<std::uint32_t, std::shared_ptr<void>> itsSharedPointerMap;
1079 571700 :
1080 594736 : //! Maps from name ids to names
1081 273504 : std::unordered_map<std::uint32_t, std::string> itsPolymorphicTypeMap;
1082 934952 :
1083 478838 : //! Maps from type hash codes to version numbers
1084 971319 : std::unordered_map<std::size_t, std::uint32_t> itsVersionedTypes;
1085 1047497 : }; // class InputArchive
1086 993604 : } // namespace cereal
1087 660919 :
1088 550604 : // This include needs to come after things such as binary_data, make_nvp, etc
1089 430517 : #include "cereal/types/common.hpp"
1090 499020 :
1091 500477 : #endif // CEREAL_CEREAL_HPP_
|