29 #ifndef CEREAL_CEREAL_HPP_ 30 #define CEREAL_CEREAL_HPP_ 32 #include <type_traits> 35 #include <unordered_map> 36 #include <unordered_set> 53 template <
class T>
inline 56 return {name.c_str(), std::forward<T>(value)};
62 template <
class T>
inline 65 return {name, std::forward<T>(value)};
71 #define CEREAL_NVP(T) ::cereal::make_nvp(#T, T) 79 template <
class T>
inline 82 return {std::forward<T>(data), size};
94 template <
class T>
inline 97 return {std::forward<T>(sz)};
107 template <
class Archive,
class T>
inline 114 template <
class Archive,
class T>
inline 132 template <
class Archive,
class T>
inline 135 return FieldSerialized::YES;
159 AllowEmptyClassElision = 1,
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 ); \ 229 #define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \ 230 namespace cereal { namespace detail { \ 231 template <> struct Version<TYPE> \ 233 static const std::uint32_t version; \ 234 static std::uint32_t registerVersion() \ 236 ::cereal::detail::StaticObject<Versions>::getInstance().mapping.emplace( \ 237 std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \ 238 return VERSION_NUMBER; \ 240 static void unused() { (void)version; } \ 242 const std::uint32_t Version<TYPE>::version = \ 243 Version<TYPE>::registerVersion(); \ 244 } } // end namespaces 263 template<
class ArchiveType, std::u
int32_t Flags = 0>
269 OutputArchive(ArchiveType *
const derived) : self(derived), itsCurrentPointerId(1), itsCurrentPolymorphicTypeId(1)
276 template <
class ... Types>
inline 279 self->process( std::forward<Types>( args )... );
292 template <
class T>
inline 295 self->process( std::forward<T>( arg ) );
303 template <
class T>
inline 306 self->process( std::forward<T>( arg ) );
323 if(addr == 0)
return 0;
325 auto id = itsSharedPointerMap.find( addr );
326 if(
id == itsSharedPointerMap.end() )
328 auto ptrId = itsCurrentPointerId++;
329 itsSharedPointerMap.insert( {addr, ptrId} );
330 return ptrId | detail::msb_32bit;
346 auto id = itsPolymorphicTypeMap.find( name );
347 if(
id == itsPolymorphicTypeMap.end() )
349 auto polyId = itsCurrentPolymorphicTypeId++;
350 itsPolymorphicTypeMap.insert( {name, polyId} );
351 return polyId | detail::msb_32bit;
373 template <
class T>
inline 374 void process( T && head )
377 self->processImpl( head );
382 template <
class T,
class ... Other>
inline 383 void process( T && head, Other && ... tail )
385 self->process( std::forward<T>( head ) );
386 self->process( std::forward<Other>( tail )... );
391 template <
class T>
inline 395 if(itsBaseClassSet.count(
id) == 0)
397 itsBaseClassSet.insert(
id);
398 self->processImpl( *b.base_ptr );
405 template <
class T>
inline 408 self->processImpl( *b.base_ptr );
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 427 template <
class T, PROCESS_IF(member_serialize)>
inline 428 ArchiveType & processImpl(T
const & t)
430 access::member_serialize(*
self, const_cast<T &>(t));
435 template <
class T, PROCESS_IF(non_member_serialize)>
inline 436 ArchiveType & processImpl(T
const & t)
443 template <
class T, PROCESS_IF(member_save)>
inline 444 ArchiveType & processImpl(T
const & t)
446 access::member_save(*
self, t);
451 template <
class T, PROCESS_IF(non_member_save)>
inline 452 ArchiveType & processImpl(T
const & t)
459 template <
class T, PROCESS_IF(member_save_minimal)>
inline 460 ArchiveType & processImpl(T
const & t)
462 self->process( access::member_save_minimal(*
self, t) );
467 template <
class T, PROCESS_IF(non_member_save_minimal)>
inline 468 ArchiveType & processImpl(T
const & t)
477 std::is_empty<T>::value> = traits::sfinae>
inline 478 ArchiveType & processImpl(T
const &)
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 &)
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 " 499 " ar( member1, member2, member3 ); \n " 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 ");
518 template <
class T>
inline typename 519 std::uint32_t registerClassVersionImpl(std::false_type)
521 static const auto hash = std::type_index(
typeid(T)).hash_code();
522 const auto insertResult = itsVersionedTypes.insert( hash );
527 if( insertResult.second )
545 template <
class T>
inline typename 546 std::uint32_t registerClassVersionImpl(std::true_type)
548 static const auto hash = std::type_index(
typeid(T)).hash_code();
556 template <
class T>
inline 557 std::uint32_t registerClassVersion()
559 using IsForwardSupport = std::integral_constant<bool, ((Flags & ForwardSupport) > 0)>;
560 return registerClassVersionImpl<T>(IsForwardSupport());
565 template <
class T, PROCESS_IF(member_versioned_serialize)>
inline 566 ArchiveType & processImpl(T
const & t)
568 access::member_serialize(*
self, const_cast<T &>(t), registerClassVersion<T>());
574 template <
class T, PROCESS_IF(non_member_versioned_serialize)>
inline 575 ArchiveType & processImpl(T
const & t)
583 template <
class T, PROCESS_IF(member_versioned_save)>
inline 584 ArchiveType & processImpl(T
const & t)
586 access::member_save(*
self, t, registerClassVersion<T>());
592 template <
class T, PROCESS_IF(non_member_versioned_save)>
inline 593 ArchiveType & processImpl(T
const & t)
601 template <
class T, PROCESS_IF(member_versioned_save_minimal)>
inline 602 ArchiveType & processImpl(T
const & t)
604 self->process( access::member_save_minimal(*
self, t, registerClassVersion<T>()) );
610 template <
class T, PROCESS_IF(non_member_versioned_save_minimal)>
inline 611 ArchiveType & processImpl(T
const & t)
620 ArchiveType *
const self;
623 std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
626 std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap;
629 std::uint32_t itsCurrentPointerId;
632 std::unordered_map<char const *, std::uint32_t> itsPolymorphicTypeMap;
635 std::uint32_t itsCurrentPolymorphicTypeId;
638 std::unordered_set<size_type> itsVersionedTypes;
658 template<
class ArchiveType, std::u
int32_t Flags = 0>
667 itsSharedPointerMap(),
668 itsPolymorphicTypeMap(),
670 wasLastFieldSerialized(FieldSerialized::YES)
677 template <
class ... Types>
inline 680 process( std::forward<Types>( args )... );
693 template <
class T>
inline 696 self->process( std::forward<T>( arg ) );
704 template <
class T>
inline 707 self->process( std::forward<T>( arg ) );
722 if(
id == 0)
return std::shared_ptr<void>(
nullptr);
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));
739 std::uint32_t
const stripped_id =
id & ~detail::msb_32bit;
740 itsSharedPointerMap[stripped_id] = ptr;
751 auto name = itsPolymorphicTypeMap.find(
id );
752 if(name == itsPolymorphicTypeMap.end())
754 throw Exception(
"Error while trying to deserialize a polymorphic pointer. Could not find type id " + std::to_string(
id));
767 std::uint32_t
const stripped_id =
id & ~detail::msb_32bit;
768 itsPolymorphicTypeMap.insert( {stripped_id, name} );
786 return wasLastFieldSerialized == FieldSerialized::YES;
796 template <
class T>
inline 797 void processPrologue( std::false_type, T && head )
800 self->processImpl( head );
807 template <
class T>
inline 808 void processPrologue( std::true_type, T && head )
811 const FieldSerialized loadRest =
prologueLoad( *
self, head );
812 if(loadRest != FieldSerialized::NO)
814 self->processImpl( head );
817 if(loadRest != FieldSerialized::INTERNAL) {
818 wasLastFieldSerialized = loadRest;
823 template <
class T>
inline 824 void process( T && head )
826 using IsForwardSupport = std::integral_constant<bool, ((Flags & ForwardSupport) > 0)>;
827 processPrologue( IsForwardSupport(), std::forward<T>( head ) );
831 template <
class T,
class ... Other>
inline 832 void process( T && head, Other && ... tail )
834 process( std::forward<T>( head ) );
835 process( std::forward<Other>( tail )... );
840 template <
class T>
inline 844 if(itsBaseClassSet.count(
id) == 0)
846 itsBaseClassSet.insert(
id);
847 self->processImpl( *b.base_ptr );
854 template <
class T>
inline 857 self->processImpl( *b.base_ptr );
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 876 template <
class T, PROCESS_IF(member_serialize)>
inline 877 ArchiveType & processImpl(T & t)
879 access::member_serialize(*
self, t);
884 template <
class T, PROCESS_IF(non_member_serialize)>
inline 885 ArchiveType & processImpl(T & t)
892 template <
class T, PROCESS_IF(member_load)>
inline 893 ArchiveType & processImpl(T & t)
895 access::member_load(*
self, t);
900 template <
class T, PROCESS_IF(non_member_load)>
inline 901 ArchiveType & processImpl(T & t)
908 template <
class T, PROCESS_IF(member_load_minimal)>
inline 909 ArchiveType & processImpl(T & t)
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);
919 template <
class T, PROCESS_IF(non_member_load_minimal)>
inline 920 ArchiveType & processImpl(T & t)
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 );
931 !traits::is_input_serializable<T, ArchiveType>::value,
932 std::is_empty<T>::value> = traits::sfinae>
inline 933 ArchiveType & processImpl(T
const &)
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 &)
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 " 954 " ar( member1, member2, member3 ); \n " 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 ");
976 template <
class T>
inline 977 std::uint32_t loadClassVersionImpl(std::false_type)
979 static const auto hash = std::type_index(
typeid(T)).hash_code();
980 auto lookupResult = itsVersionedTypes.find( hash );
982 if( lookupResult != itsVersionedTypes.end() )
983 return lookupResult->second;
988 process( make_nvp<ArchiveType>(
"cereal_class_version", version) );
989 itsVersionedTypes.emplace_hint( lookupResult, hash, version.version_id );
991 return version.version_id;
995 template <
class T>
inline 996 std::uint32_t loadClassVersionImpl(std::true_type)
999 process( make_nvp<ArchiveType>(
"cereal_class_version", version ) );
1000 return version.version_id;
1003 template <
class T>
inline 1004 std::uint32_t loadClassVersion()
1006 return loadClassVersionImpl<T>(std::integral_constant<bool, ((Flags & ForwardSupport) > 0)>());
1011 template <
class T, PROCESS_IF(member_versioned_serialize)>
inline 1012 ArchiveType & processImpl(T & t)
1014 const auto version = loadClassVersion<T>();
1015 access::member_serialize(*
self, t, version);
1021 template <
class T, PROCESS_IF(non_member_versioned_serialize)>
inline 1022 ArchiveType & processImpl(T & t)
1024 const auto version = loadClassVersion<T>();
1031 template <
class T, PROCESS_IF(member_versioned_load)>
inline 1032 ArchiveType & processImpl(T & t)
1034 const auto version = loadClassVersion<T>();
1035 access::member_load(*
self, t, version);
1041 template <
class T, PROCESS_IF(non_member_versioned_load)>
inline 1042 ArchiveType & processImpl(T & t)
1044 const auto version = loadClassVersion<T>();
1051 template <
class T, PROCESS_IF(member_versioned_load_minimal)>
inline 1052 ArchiveType & processImpl(T & t)
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);
1064 template <
class T, PROCESS_IF(non_member_versioned_load_minimal)>
inline 1065 ArchiveType & processImpl(T & t)
1068 const auto version = loadClassVersion<T>();
1069 typename traits::has_non_member_versioned_save_minimal<T, OutArchiveType>::type value;
1070 self->process(value);
1078 ArchiveType *
const self;
1081 std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
1084 std::unordered_map<std::uint32_t, std::shared_ptr<void>> itsSharedPointerMap;
1087 std::unordered_map<std::uint32_t, std::string> itsPolymorphicTypeMap;
1090 std::unordered_map<std::size_t, std::uint32_t> itsVersionedTypes;
1093 FieldSerialized wasLastFieldSerialized;
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
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)
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.
Casts a derived class to its non-virtual base class in a way that safely supports abstract classes...
Definition: base_class.hpp:99
#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
#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.
#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
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
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
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 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