cereal_fwd
Fork of cereal library adding archive supporting forward compatibility
cereal.hpp
Go to the documentation of this file.
1 
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 <unordered_map>
36 #include <unordered_set>
37 #include <vector>
38 #include <cstddef>
39 #include <cstdint>
40 #include <functional>
41 
42 #include <cereal/macros.hpp>
46 
47 namespace cereal
48 {
49  // ######################################################################
51 
53  template <class T> inline
54  NameValuePair<T> make_nvp( std::string const & name, T && value )
55  {
56  return {name.c_str(), std::forward<T>(value)};
57  }
58 
60 
62  template <class T> inline
63  NameValuePair<T> make_nvp( const char * name, T && value )
64  {
65  return {name, std::forward<T>(value)};
66  }
67 
69 
71  #define CEREAL_NVP(T) ::cereal::make_nvp(#T, T)
72 
73  // ######################################################################
75 
79  template <class T> inline
80  BinaryData<T> binary_data( T && data, size_t size )
81  {
82  return {std::forward<T>(data), size};
83  }
84 
85  // ######################################################################
87 
94  template <class T> inline
96  {
97  return {std::forward<T>(sz)};
98  }
99 
100  // ######################################################################
103 
107  template <class Archive, class T> inline
108  void prologue( Archive & /* archive */, T const & /* data */)
109  { }
110 
113 
114  template <class Archive, class T> inline
115  void epilogue( Archive & /* archive */, T const & /* data */)
116  { }
117 
120 
132  template <class Archive, class T> inline
133  FieldSerialized prologueLoad( Archive & /* archive */, T const & /* data */)
134  {
135  return FieldSerialized::YES;
136  }
137  // ######################################################################
139 
158  enum Flags {
159  AllowEmptyClassElision = 1,
160  ForwardSupport = 2
161  };
162 
163  // ######################################################################
165 
171  #define CEREAL_REGISTER_ARCHIVE(Archive) \
172  namespace cereal { namespace detail { \
173  template <class T, class BindingTag> \
174  typename polymorphic_serialization_support<Archive, T>::type \
175  instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \
176  } } /* end namespaces */
177 
178  // ######################################################################
180 
229  #define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \
230  namespace cereal { namespace detail { \
231  template <> struct Version<TYPE> \
232  { \
233  static const std::uint32_t version; \
234  static std::uint32_t registerVersion() \
235  { \
236  ::cereal::detail::StaticObject<Versions>::getInstance().mapping.emplace( \
237  std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \
238  return VERSION_NUMBER; \
239  } \
240  static void unused() { (void)version; } \
241  }; /* end Version */ \
242  const std::uint32_t Version<TYPE>::version = \
243  Version<TYPE>::registerVersion(); \
244  } } // end namespaces
245 
246  // ######################################################################
248 
263  template<class ArchiveType, std::uint32_t Flags = 0>
265  {
266  public:
268 
269  OutputArchive(ArchiveType * const derived) : self(derived), itsCurrentPointerId(1), itsCurrentPolymorphicTypeId(1)
270  { }
271 
272  OutputArchive & operator=( OutputArchive const & ) = delete;
273 
275 
276  template <class ... Types> inline
277  ArchiveType & operator()( Types && ... args )
278  {
279  self->process( std::forward<Types>( args )... );
280  return *self;
281  }
282 
286 
289 
292  template <class T> inline
293  ArchiveType & operator&( T && arg )
294  {
295  self->process( std::forward<T>( arg ) );
296  return *self;
297  }
298 
300 
303  template <class T> inline
304  ArchiveType & operator<<( T && arg )
305  {
306  self->process( std::forward<T>( arg ) );
307  return *self;
308  }
309 
311 
313 
320  inline std::uint32_t registerSharedPointer( void const * addr )
321  {
322  // Handle null pointers by just returning 0
323  if(addr == 0) return 0;
324 
325  auto id = itsSharedPointerMap.find( addr );
326  if( id == itsSharedPointerMap.end() )
327  {
328  auto ptrId = itsCurrentPointerId++;
329  itsSharedPointerMap.insert( {addr, ptrId} );
330  return ptrId | detail::msb_32bit; // mask MSB to be 1
331  }
332  else
333  return id->second;
334  }
335 
337 
344  inline std::uint32_t registerPolymorphicType( char const * name )
345  {
346  auto id = itsPolymorphicTypeMap.find( name );
347  if( id == itsPolymorphicTypeMap.end() )
348  {
349  auto polyId = itsCurrentPolymorphicTypeId++;
350  itsPolymorphicTypeMap.insert( {name, polyId} );
351  return polyId | detail::msb_32bit; // mask MSB to be 1
352  }
353  else
354  return id->second;
355  }
357 
362  bool wasSerialized() const
363  {
364  return true;
365  }
367  using is_saving = std::true_type;
369  using is_loading = std::false_type;
370 
371  private:
373  template <class T> inline
374  void process( T && head )
375  {
376  prologue( *self, head );
377  self->processImpl( head );
378  epilogue( *self, head );
379  }
380 
382  template <class T, class ... Other> inline
383  void process( T && head, Other && ... tail )
384  {
385  self->process( std::forward<T>( head ) );
386  self->process( std::forward<Other>( tail )... );
387  }
388 
390 
391  template <class T> inline
392  ArchiveType & processImpl(virtual_base_class<T> const & b)
393  {
394  traits::detail::base_class_id id(b.base_ptr);
395  if(itsBaseClassSet.count(id) == 0)
396  {
397  itsBaseClassSet.insert(id);
398  self->processImpl( *b.base_ptr );
399  }
400  return *self;
401  }
402 
404 
405  template <class T> inline
406  ArchiveType & processImpl(base_class<T> const & b)
407  {
408  self->processImpl( *b.base_ptr );
409  return *self;
410  }
411 
413 
419  #define PROCESS_IF(name) \
420  traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \
421  !traits::has_invalid_output_versioning<T, ArchiveType>::value, \
422  (traits::is_output_serializable<T, ArchiveType>::value && \
423  (traits::is_specialized_##name<T, ArchiveType>::value || \
424  !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae
425 
427  template <class T, PROCESS_IF(member_serialize)> inline
428  ArchiveType & processImpl(T const & t)
429  {
430  access::member_serialize(*self, const_cast<T &>(t));
431  return *self;
432  }
433 
435  template <class T, PROCESS_IF(non_member_serialize)> inline
436  ArchiveType & processImpl(T const & t)
437  {
438  CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t));
439  return *self;
440  }
441 
443  template <class T, PROCESS_IF(member_save)> inline
444  ArchiveType & processImpl(T const & t)
445  {
446  access::member_save(*self, t);
447  return *self;
448  }
449 
451  template <class T, PROCESS_IF(non_member_save)> inline
452  ArchiveType & processImpl(T const & t)
453  {
454  CEREAL_SAVE_FUNCTION_NAME(*self, t);
455  return *self;
456  }
457 
459  template <class T, PROCESS_IF(member_save_minimal)> inline
460  ArchiveType & processImpl(T const & t)
461  {
462  self->process( access::member_save_minimal(*self, t) );
463  return *self;
464  }
465 
467  template <class T, PROCESS_IF(non_member_save_minimal)> inline
468  ArchiveType & processImpl(T const & t)
469  {
470  self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t) );
471  return *self;
472  }
473 
475  template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
477  std::is_empty<T>::value> = traits::sfinae> inline
478  ArchiveType & processImpl(T const &)
479  {
480  return *self;
481  }
482 
484 
487  template <class T, traits::EnableIf<traits::has_invalid_output_versioning<T, ArchiveType>::value ||
489  (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
490  ArchiveType & processImpl(T const &)
491  {
493  "cereal could not find any output serialization functions for the provided type and archive combination. \n\n "
494  "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
495  "Serialize functions generally have the following signature: \n\n "
496  "template<class Archive> \n "
497  " void serialize(Archive & ar) \n "
498  " { \n "
499  " ar( member1, member2, member3 ); \n "
500  " } \n\n " );
501 
503  "cereal found more than one compatible output serialization function for the provided type and archive combination. \n\n "
504  "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
505  "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
506  "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
507  "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
508 
509  return *self;
510  }
511 
513 
518  template <class T> inline typename
519  std::uint32_t registerClassVersionImpl(std::false_type)
520  {
521  static const auto hash = std::type_index(typeid(T)).hash_code();
522  const auto insertResult = itsVersionedTypes.insert( hash );
524  const auto version =
526 
527  if( insertResult.second ) // insertion took place, serialize the version number
528  process( make_nvp<ArchiveType>("cereal_class_version", detail::VersionIdTag<T>(version)) );
529 
530  return version;
531  }
532 
534 
545  template <class T> inline typename
546  std::uint32_t registerClassVersionImpl(std::true_type)
547  {
548  static const auto hash = std::type_index(typeid(T)).hash_code();
550  const auto version =
552  process( make_nvp<ArchiveType>("cereal_class_version", detail::VersionIdTag<T>(version)) );
553  return version;
554  }
555 
556  template <class T> inline
557  std::uint32_t registerClassVersion()
558  {
559  using IsForwardSupport = std::integral_constant<bool, ((Flags & ForwardSupport) > 0)>;
560  return registerClassVersionImpl<T>(IsForwardSupport());
561  }
562 
564 
565  template <class T, PROCESS_IF(member_versioned_serialize)> inline
566  ArchiveType & processImpl(T const & t)
567  {
568  access::member_serialize(*self, const_cast<T &>(t), registerClassVersion<T>());
569  return *self;
570  }
571 
573 
574  template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
575  ArchiveType & processImpl(T const & t)
576  {
577  CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t), registerClassVersion<T>());
578  return *self;
579  }
580 
582 
583  template <class T, PROCESS_IF(member_versioned_save)> inline
584  ArchiveType & processImpl(T const & t)
585  {
586  access::member_save(*self, t, registerClassVersion<T>());
587  return *self;
588  }
589 
591 
592  template <class T, PROCESS_IF(non_member_versioned_save)> inline
593  ArchiveType & processImpl(T const & t)
594  {
595  CEREAL_SAVE_FUNCTION_NAME(*self, t, registerClassVersion<T>());
596  return *self;
597  }
598 
600 
601  template <class T, PROCESS_IF(member_versioned_save_minimal)> inline
602  ArchiveType & processImpl(T const & t)
603  {
604  self->process( access::member_save_minimal(*self, t, registerClassVersion<T>()) );
605  return *self;
606  }
607 
609 
610  template <class T, PROCESS_IF(non_member_versioned_save_minimal)> inline
611  ArchiveType & processImpl(T const & t)
612  {
613  self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t, registerClassVersion<T>()) );
614  return *self;
615  }
616 
617  #undef PROCESS_IF
618 
619  private:
620  ArchiveType * const self;
621 
623  std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
624 
626  std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap;
627 
629  std::uint32_t itsCurrentPointerId;
630 
632  std::unordered_map<char const *, std::uint32_t> itsPolymorphicTypeMap;
633 
635  std::uint32_t itsCurrentPolymorphicTypeId;
636 
638  std::unordered_set<size_type> itsVersionedTypes;
639  }; // class OutputArchive
640 
641  // ######################################################################
643 
658  template<class ArchiveType, std::uint32_t Flags = 0>
660  {
661  public:
663 
664  InputArchive(ArchiveType * const derived) :
665  self(derived),
666  itsBaseClassSet(),
667  itsSharedPointerMap(),
668  itsPolymorphicTypeMap(),
669  itsVersionedTypes(),
670  wasLastFieldSerialized(FieldSerialized::YES)
671  { }
672 
673  InputArchive & operator=( InputArchive const & ) = delete;
674 
676 
677  template <class ... Types> inline
678  ArchiveType & operator()( Types && ... args )
679  {
680  process( std::forward<Types>( args )... );
681  return *self;
682  }
683 
687 
690 
693  template <class T> inline
694  ArchiveType & operator&( T && arg )
695  {
696  self->process( std::forward<T>( arg ) );
697  return *self;
698  }
699 
701 
704  template <class T> inline
705  ArchiveType & operator>>( T && arg )
706  {
707  self->process( std::forward<T>( arg ) );
708  return *self;
709  }
710 
712 
714 
720  inline std::shared_ptr<void> getSharedPointer(std::uint32_t const id)
721  {
722  if(id == 0) return std::shared_ptr<void>(nullptr);
723 
724  auto iter = itsSharedPointerMap.find( id );
725  if(iter == itsSharedPointerMap.end())
726  throw Exception("Error while trying to deserialize a smart pointer. Could not find id " + std::to_string(id));
727 
728  return iter->second;
729  }
730 
732 
737  inline void registerSharedPointer(std::uint32_t const id, std::shared_ptr<void> ptr)
738  {
739  std::uint32_t const stripped_id = id & ~detail::msb_32bit;
740  itsSharedPointerMap[stripped_id] = ptr;
741  }
742 
744 
749  inline std::string getPolymorphicName(std::uint32_t const id)
750  {
751  auto name = itsPolymorphicTypeMap.find( id );
752  if(name == itsPolymorphicTypeMap.end())
753  {
754  throw Exception("Error while trying to deserialize a polymorphic pointer. Could not find type id " + std::to_string(id));
755  }
756  return name->second;
757  }
758 
760 
765  inline void registerPolymorphicName(std::uint32_t const id, std::string const & name)
766  {
767  std::uint32_t const stripped_id = id & ~detail::msb_32bit;
768  itsPolymorphicTypeMap.insert( {stripped_id, name} );
769  }
770 
772 
784  bool wasSerialized() const
785  {
786  return wasLastFieldSerialized == FieldSerialized::YES;
787  }
788 
790  using is_saving = std::false_type;
792  using is_loading = std::true_type;
793 
794  private:
796  template <class T> inline
797  void processPrologue( std::false_type, T && head )
798  {
799  prologue( *self, head );
800  self->processImpl( head );
801  epilogue( *self, head );
802  }
803 
805 
807  template <class T> inline
808  void processPrologue( std::true_type, T && head )
809  {
810  // TODO add likely predicate
811  const FieldSerialized loadRest = prologueLoad( *self, head );
812  if(loadRest != FieldSerialized::NO)
813  {
814  self->processImpl( head );
815  epilogue( *self, head );
816  }
817  if(loadRest != FieldSerialized::INTERNAL) {
818  wasLastFieldSerialized = loadRest;
819  }
820  }
821 
823  template <class T> inline
824  void process( T && head )
825  {
826  using IsForwardSupport = std::integral_constant<bool, ((Flags & ForwardSupport) > 0)>;
827  processPrologue( IsForwardSupport(), std::forward<T>( head ) );
828  }
829 
831  template <class T, class ... Other> inline
832  void process( T && head, Other && ... tail )
833  {
834  process( std::forward<T>( head ) );
835  process( std::forward<Other>( tail )... );
836  }
837 
839 
840  template <class T> inline
841  ArchiveType & processImpl(virtual_base_class<T> & b)
842  {
843  traits::detail::base_class_id id(b.base_ptr);
844  if(itsBaseClassSet.count(id) == 0)
845  {
846  itsBaseClassSet.insert(id);
847  self->processImpl( *b.base_ptr );
848  }
849  return *self;
850  }
851 
853 
854  template <class T> inline
855  ArchiveType & processImpl(base_class<T> & b)
856  {
857  self->processImpl( *b.base_ptr );
858  return *self;
859  }
860 
862 
868  #define PROCESS_IF(name) \
869  traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \
870  !traits::has_invalid_input_versioning<T, ArchiveType>::value, \
871  (traits::is_input_serializable<T, ArchiveType>::value && \
872  (traits::is_specialized_##name<T, ArchiveType>::value || \
873  !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae
874 
876  template <class T, PROCESS_IF(member_serialize)> inline
877  ArchiveType & processImpl(T & t)
878  {
879  access::member_serialize(*self, t);
880  return *self;
881  }
882 
884  template <class T, PROCESS_IF(non_member_serialize)> inline
885  ArchiveType & processImpl(T & t)
886  {
888  return *self;
889  }
890 
892  template <class T, PROCESS_IF(member_load)> inline
893  ArchiveType & processImpl(T & t)
894  {
895  access::member_load(*self, t);
896  return *self;
897  }
898 
900  template <class T, PROCESS_IF(non_member_load)> inline
901  ArchiveType & processImpl(T & t)
902  {
903  CEREAL_LOAD_FUNCTION_NAME(*self, t);
904  return *self;
905  }
906 
908  template <class T, PROCESS_IF(member_load_minimal)> inline
909  ArchiveType & processImpl(T & t)
910  {
911  using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
912  typename traits::has_member_save_minimal<T, OutArchiveType>::type value;
913  self->process( value );
914  access::member_load_minimal(*self, t, value);
915  return *self;
916  }
917 
919  template <class T, PROCESS_IF(non_member_load_minimal)> inline
920  ArchiveType & processImpl(T & t)
921  {
922  using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
923  typename traits::has_non_member_save_minimal<T, OutArchiveType>::type value;
924  self->process( value );
925  CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value);
926  return *self;
927  }
928 
930  template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
931  !traits::is_input_serializable<T, ArchiveType>::value,
932  std::is_empty<T>::value> = traits::sfinae> inline
933  ArchiveType & processImpl(T const &)
934  {
935  return *self;
936  }
937 
939 
942  template <class T, traits::EnableIf<traits::has_invalid_input_versioning<T, ArchiveType>::value ||
943  (!traits::is_input_serializable<T, ArchiveType>::value &&
944  (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
945  ArchiveType & processImpl(T const &)
946  {
947  static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value != 0,
948  "cereal could not find any input serialization functions for the provided type and archive combination. \n\n "
949  "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
950  "Serialize functions generally have the following signature: \n\n "
951  "template<class Archive> \n "
952  " void serialize(Archive & ar) \n "
953  " { \n "
954  " ar( member1, member2, member3 ); \n "
955  " } \n\n " );
956 
957  static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value < 2,
958  "cereal found more than one compatible input serialization function for the provided type and archive combination. \n\n "
959  "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
960  "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
961  "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
962  "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
963 
964  return *self;
965  }
966 
968  template <class A, class B, bool C, bool D, bool E, bool F> friend struct detail::Construct;
969 
971 
976  template <class T> inline
977  std::uint32_t loadClassVersionImpl(std::false_type)
978  {
979  static const auto hash = std::type_index(typeid(T)).hash_code();
980  auto lookupResult = itsVersionedTypes.find( hash );
981 
982  if( lookupResult != itsVersionedTypes.end() ) // already exists
983  return lookupResult->second;
984  else // need to load
985  {
986  detail::VersionIdTag<T> version;
987 
988  process( make_nvp<ArchiveType>("cereal_class_version", version) );
989  itsVersionedTypes.emplace_hint( lookupResult, hash, version.version_id );
990 
991  return version.version_id;
992  }
993  }
994 
995  template <class T> inline
996  std::uint32_t loadClassVersionImpl(std::true_type)
997  {
998  detail::VersionIdTag<T> version;
999  process( make_nvp<ArchiveType>("cereal_class_version", version ) );
1000  return version.version_id;
1001  }
1002 
1003  template <class T> inline
1004  std::uint32_t loadClassVersion()
1005  {
1006  return loadClassVersionImpl<T>(std::integral_constant<bool, ((Flags & ForwardSupport) > 0)>());
1007  }
1008 
1010 
1011  template <class T, PROCESS_IF(member_versioned_serialize)> inline
1012  ArchiveType & processImpl(T & t)
1013  {
1014  const auto version = loadClassVersion<T>();
1015  access::member_serialize(*self, t, version);
1016  return *self;
1017  }
1018 
1020 
1021  template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
1022  ArchiveType & processImpl(T & t)
1023  {
1024  const auto version = loadClassVersion<T>();
1025  CEREAL_SERIALIZE_FUNCTION_NAME(*self, t, version);
1026  return *self;
1027  }
1028 
1030 
1031  template <class T, PROCESS_IF(member_versioned_load)> inline
1032  ArchiveType & processImpl(T & t)
1033  {
1034  const auto version = loadClassVersion<T>();
1035  access::member_load(*self, t, version);
1036  return *self;
1037  }
1038 
1040 
1041  template <class T, PROCESS_IF(non_member_versioned_load)> inline
1042  ArchiveType & processImpl(T & t)
1043  {
1044  const auto version = loadClassVersion<T>();
1045  CEREAL_LOAD_FUNCTION_NAME(*self, t, version);
1046  return *self;
1047  }
1048 
1050 
1051  template <class T, PROCESS_IF(member_versioned_load_minimal)> inline
1052  ArchiveType & processImpl(T & t)
1053  {
1054  using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
1055  const auto version = loadClassVersion<T>();
1056  typename traits::has_member_versioned_save_minimal<T, OutArchiveType>::type value;
1057  self->process(value);
1058  access::member_load_minimal(*self, t, value, version);
1059  return *self;
1060  }
1061 
1063 
1064  template <class T, PROCESS_IF(non_member_versioned_load_minimal)> inline
1065  ArchiveType & processImpl(T & t)
1066  {
1067  using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
1068  const auto version = loadClassVersion<T>();
1069  typename traits::has_non_member_versioned_save_minimal<T, OutArchiveType>::type value;
1070  self->process(value);
1071  CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value, version);
1072  return *self;
1073  }
1074 
1075  #undef PROCESS_IF
1076 
1077  private:
1078  ArchiveType * const self;
1079 
1081  std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
1082 
1084  std::unordered_map<std::uint32_t, std::shared_ptr<void>> itsSharedPointerMap;
1085 
1087  std::unordered_map<std::uint32_t, std::string> itsPolymorphicTypeMap;
1088 
1090  std::unordered_map<std::size_t, std::uint32_t> itsVersionedTypes;
1091 
1093  FieldSerialized wasLastFieldSerialized;
1094  }; // class InputArchive
1095 } // namespace cereal
1096 
1097 // This include needs to come after things such as binary_data, make_nvp, etc
1098 #include <cereal/types/common.hpp>
1099 
1100 #endif // CEREAL_CEREAL_HPP_
The number of output serialization functions available.
Definition: traits.hpp:1071
A wrapper around size metadata.
Definition: helpers.hpp:271
Casts a derived class to its virtual base class in a way that allows cereal to track inheritance...
Definition: base_class.hpp:186
ArchiveType & operator &(T &&arg)
Serializes passed in data.
Definition: cereal.hpp:694
std::false_type is_loading
indicates if archive is used for loading
Definition: cereal.hpp:369
FieldSerialized prologueLoad(Archive &, T const &)
Definition: cereal.hpp:133
Support for base classes (virtual and non-virtual)
std::shared_ptr< void > getSharedPointer(std::uint32_t const id)
Retrieves a shared pointer given a unique key for it.
Definition: cereal.hpp:720
typename detail::EnableIfHelper< Conditions... >::type EnableIf
Provides a way to enable a function if conditions are met.
Definition: traits.hpp:116
Version information class.
Definition: helpers.hpp:580
NameValuePair< T > make_nvp(std::string const &name, T &&value)
Creates a name value pair.
Definition: cereal.hpp:54
std::true_type is_saving
indicates if archive is used for saving
Definition: cereal.hpp:367
Internal type trait support.
std::string getPolymorphicName(std::uint32_t const id)
Retrieves the string for a polymorphic type given a unique key for it.
Definition: cereal.hpp:749
Casts a derived class to its non-virtual base class in a way that safely supports abstract classes...
Definition: base_class.hpp:99
The base input archive class.
Definition: cereal.hpp:659
#define CEREAL_SERIALIZE_FUNCTION_NAME
The serialization/deserialization function name to search for.
Definition: macros.hpp:64
A wrapper around polymorphic id.
Definition: helpers.hpp:369
InputArchive(ArchiveType *const derived)
Construct the input archive.
Definition: cereal.hpp:664
#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME
The serialization (save_minimal) function name to search for.
Definition: macros.hpp:92
void prologue(Archive &, T const &)
Definition: cereal.hpp:108
SizeTag< T > make_size_tag(T &&sz)
Creates a size tag from some variable.
Definition: cereal.hpp:95
std::uint32_t registerPolymorphicType(char const *name)
Registers a polymorphic type name with the archive.
Definition: cereal.hpp:344
Support common types - always included automatically.
Internal helper functionality.
Flags
Special flags for archives.
Definition: cereal.hpp:158
static LockGuard lock()
Attempts to lock this static object for the current scope.
Definition: static_object.hpp:109
Definition: access.hpp:40
NameValuePair< T > make_nvp(const char *name, T &&value)
Creates a name value pair.
Definition: cereal.hpp:63
For holding name value pairs.
Definition: helpers.hpp:135
Definition: traits.hpp:1089
Preprocessor macros that can customise the cereal library.
void registerSharedPointer(std::uint32_t const id, std::shared_ptr< void > ptr)
Registers a shared pointer to its unique identifier.
Definition: cereal.hpp:737
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:71
ArchiveType & operator &(T &&arg)
Serializes passed in data.
Definition: cereal.hpp:293
#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME
The deserialization (load_minimal) function name to search for.
Definition: macros.hpp:85
std::uint32_t registerSharedPointer(void const *addr)
Registers a shared pointer with the archive.
Definition: cereal.hpp:320
void registerPolymorphicName(std::uint32_t const id, std::string const &name)
Registers a polymorphic name string to its unique identifier.
Definition: cereal.hpp:765
A wrapper around data that can be serialized in a binary fashion.
Definition: helpers.hpp:207
OutputArchive(ArchiveType *const derived)
Construct the output archive.
Definition: cereal.hpp:269
ArchiveType & operator>>(T &&arg)
Serializes passed in data.
Definition: cereal.hpp:705
std::true_type is_loading
indicates if archive is used for loading
Definition: cereal.hpp:792
std::false_type is_saving
indicates if archive is used for saving
Definition: cereal.hpp:790
ArchiveType & operator()(Types &&... args)
Serializes all passed in data.
Definition: cereal.hpp:678
Definition: helpers.hpp:228
The base output archive class.
Definition: cereal.hpp:264
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:78
ArchiveType & operator()(Types &&... args)
Serializes all passed in data.
Definition: cereal.hpp:277
Definition: traits.hpp:1325
Definition: helpers.hpp:240
ArchiveType & operator<<(T &&arg)
Serializes passed in data.
Definition: cereal.hpp:304
Definition: traits.hpp:1123
A static, pre-execution object.
Definition: static_object.hpp:67
bool wasSerialized() const
Indicates if last field was loaded.
Definition: cereal.hpp:784
bool wasSerialized() const
Indicates if last field was saved.
Definition: cereal.hpp:362
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48
BinaryData< T > binary_data(T &&data, size_t size)
Convenience function to create binary data for both const and non const pointers. ...
Definition: cereal.hpp:80
void epilogue(Archive &, T const &)
Definition: cereal.hpp:115