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 131 enum Flags { AllowEmptyClassElision = 1 };
141 #define CEREAL_REGISTER_ARCHIVE(Archive) \ 142 namespace cereal { namespace detail { \ 143 template <class T, class BindingTag> \ 144 typename polymorphic_serialization_support<Archive, T>::type \ 145 instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \ 199 #define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \ 200 namespace cereal { namespace detail { \ 201 template <> struct Version<TYPE> \ 203 static const std::uint32_t version; \ 204 static std::uint32_t registerVersion() \ 206 ::cereal::detail::StaticObject<Versions>::getInstance().mapping.emplace( \ 207 std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \ 208 return VERSION_NUMBER; \ 210 static void unused() { (void)version; } \ 212 const std::uint32_t Version<TYPE>::version = \ 213 Version<TYPE>::registerVersion(); \ 214 } } // end namespaces 233 template<
class ArchiveType, std::u
int32_t Flags = 0>
239 OutputArchive(ArchiveType *
const derived) : self(derived), itsCurrentPointerId(1), itsCurrentPolymorphicTypeId(1)
246 template <
class ... Types>
inline 249 self->process( std::forward<Types>( args )... );
276 template <
class T>
inline 279 self->process( std::forward<T>( arg ) );
287 template <
class T>
inline 290 self->process( std::forward<T>( arg ) );
307 if(addr == 0)
return 0;
309 auto id = itsSharedPointerMap.find( addr );
310 if(
id == itsSharedPointerMap.end() )
312 auto ptrId = itsCurrentPointerId++;
313 itsSharedPointerMap.insert( {addr, ptrId} );
314 return ptrId | detail::msb_32bit;
330 auto id = itsPolymorphicTypeMap.find( name );
331 if(
id == itsPolymorphicTypeMap.end() )
333 auto polyId = itsCurrentPolymorphicTypeId++;
334 itsPolymorphicTypeMap.insert( {name, polyId} );
335 return polyId | detail::msb_32bit;
343 template <
class T>
inline 344 void process( T && head )
347 self->processImpl( head );
352 template <
class T,
class ... Other>
inline 353 void process( T && head, Other && ... tail )
355 self->process( std::forward<T>( head ) );
356 self->process( std::forward<Other>( tail )... );
361 template <
class T>
inline 365 if(itsBaseClassSet.count(
id) == 0)
367 itsBaseClassSet.insert(
id);
368 self->processImpl( *b.base_ptr );
375 template <
class T>
inline 378 self->processImpl( *b.base_ptr );
389 #define PROCESS_IF(name) \ 390 traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \ 391 !traits::has_invalid_output_versioning<T, ArchiveType>::value, \ 392 (traits::is_output_serializable<T, ArchiveType>::value && \ 393 (traits::is_specialized_##name<T, ArchiveType>::value || \ 394 !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae 397 template <
class T, PROCESS_IF(member_serialize)>
inline 398 ArchiveType & processImpl(T
const & t)
400 access::member_serialize(*
self, const_cast<T &>(t));
405 template <
class T, PROCESS_IF(non_member_serialize)>
inline 406 ArchiveType & processImpl(T
const & t)
413 template <
class T, PROCESS_IF(member_save)>
inline 414 ArchiveType & processImpl(T
const & t)
416 access::member_save(*
self, t);
421 template <
class T, PROCESS_IF(non_member_save)>
inline 422 ArchiveType & processImpl(T
const & t)
429 template <
class T, PROCESS_IF(member_save_minimal)>
inline 430 ArchiveType & processImpl(T
const & t)
432 self->process( access::member_save_minimal(*
self, t) );
437 template <
class T, PROCESS_IF(non_member_save_minimal)>
inline 438 ArchiveType & processImpl(T
const & t)
447 std::is_empty<T>::value> = traits::sfinae>
inline 448 ArchiveType & processImpl(T
const &)
457 template <class T, traits::EnableIf<traits::has_invalid_output_versioning<T, ArchiveType>::value ||
459 (!(
Flags & AllowEmptyClassElision) || ((
Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae>
inline 460 ArchiveType & processImpl(T
const &)
463 "cereal could not find any output serialization functions for the provided type and archive combination. \n\n " 464 "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " 465 "Serialize functions generally have the following signature: \n\n " 466 "template<class Archive> \n " 467 " void serialize(Archive & ar) \n " 469 " ar( member1, member2, member3 ); \n " 473 "cereal found more than one compatible output serialization function for the provided type and archive combination. \n\n " 474 "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " 475 "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n " 476 "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n " 477 "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
488 template <
class T>
inline 489 std::uint32_t registerClassVersion()
491 static const auto hash = std::type_index(
typeid(T)).hash_code();
492 const auto insertResult = itsVersionedTypes.insert( hash );
497 if( insertResult.second )
498 process( make_nvp<ArchiveType>(
"cereal_class_version", version) );
505 template <
class T, PROCESS_IF(member_versioned_serialize)>
inline 506 ArchiveType & processImpl(T
const & t)
508 access::member_serialize(*
self, const_cast<T &>(t), registerClassVersion<T>());
514 template <
class T, PROCESS_IF(non_member_versioned_serialize)>
inline 515 ArchiveType & processImpl(T
const & t)
523 template <
class T, PROCESS_IF(member_versioned_save)>
inline 524 ArchiveType & processImpl(T
const & t)
526 access::member_save(*
self, t, registerClassVersion<T>());
532 template <
class T, PROCESS_IF(non_member_versioned_save)>
inline 533 ArchiveType & processImpl(T
const & t)
541 template <
class T, PROCESS_IF(member_versioned_save_minimal)>
inline 542 ArchiveType & processImpl(T
const & t)
544 self->process( access::member_save_minimal(*
self, t, registerClassVersion<T>()) );
550 template <
class T, PROCESS_IF(non_member_versioned_save_minimal)>
inline 551 ArchiveType & processImpl(T
const & t)
560 ArchiveType *
const self;
563 std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
566 std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap;
569 std::uint32_t itsCurrentPointerId;
572 std::unordered_map<char const *, std::uint32_t> itsPolymorphicTypeMap;
575 std::uint32_t itsCurrentPolymorphicTypeId;
578 std::unordered_set<size_type> itsVersionedTypes;
598 template<
class ArchiveType, std::u
int32_t Flags = 0>
607 itsSharedPointerMap(),
608 itsPolymorphicTypeMap(),
616 template <
class ... Types>
inline 619 process( std::forward<Types>( args )... );
646 template <
class T>
inline 649 self->process( std::forward<T>( arg ) );
657 template <
class T>
inline 660 self->process( std::forward<T>( arg ) );
675 if(
id == 0)
return std::shared_ptr<void>(
nullptr);
677 auto iter = itsSharedPointerMap.find(
id );
678 if(iter == itsSharedPointerMap.end())
679 throw Exception(
"Error while trying to deserialize a smart pointer. Could not find id " + std::to_string(
id));
692 std::uint32_t
const stripped_id =
id & ~detail::msb_32bit;
693 itsSharedPointerMap[stripped_id] = ptr;
704 auto name = itsPolymorphicTypeMap.find(
id );
705 if(name == itsPolymorphicTypeMap.end())
707 throw Exception(
"Error while trying to deserialize a polymorphic pointer. Could not find type id " + std::to_string(
id));
720 std::uint32_t
const stripped_id =
id & ~detail::msb_32bit;
721 itsPolymorphicTypeMap.insert( {stripped_id, name} );
726 template <
class T>
inline 727 void process( T && head )
730 self->processImpl( head );
735 template <
class T,
class ... Other>
inline 736 void process( T && head, Other && ... tail )
738 process( std::forward<T>( head ) );
739 process( std::forward<Other>( tail )... );
744 template <
class T>
inline 748 if(itsBaseClassSet.count(
id) == 0)
750 itsBaseClassSet.insert(
id);
751 self->processImpl( *b.base_ptr );
758 template <
class T>
inline 761 self->processImpl( *b.base_ptr );
772 #define PROCESS_IF(name) \ 773 traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \ 774 !traits::has_invalid_input_versioning<T, ArchiveType>::value, \ 775 (traits::is_input_serializable<T, ArchiveType>::value && \ 776 (traits::is_specialized_##name<T, ArchiveType>::value || \ 777 !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae 780 template <
class T, PROCESS_IF(member_serialize)>
inline 781 ArchiveType & processImpl(T & t)
783 access::member_serialize(*
self, t);
788 template <
class T, PROCESS_IF(non_member_serialize)>
inline 789 ArchiveType & processImpl(T & t)
796 template <
class T, PROCESS_IF(member_load)>
inline 797 ArchiveType & processImpl(T & t)
799 access::member_load(*
self, t);
804 template <
class T, PROCESS_IF(non_member_load)>
inline 805 ArchiveType & processImpl(T & t)
812 template <
class T, PROCESS_IF(member_load_minimal)>
inline 813 ArchiveType & processImpl(T & t)
815 using OutArchiveType =
typename traits::detail::get_output_from_input<ArchiveType>::type;
816 typename traits::has_member_save_minimal<T, OutArchiveType>::type value;
817 self->process( value );
818 access::member_load_minimal(*
self, t, value);
823 template <
class T, PROCESS_IF(non_member_load_minimal)>
inline 824 ArchiveType & processImpl(T & t)
826 using OutArchiveType =
typename traits::detail::get_output_from_input<ArchiveType>::type;
827 typename traits::has_non_member_save_minimal<T, OutArchiveType>::type value;
828 self->process( value );
835 !traits::is_input_serializable<T, ArchiveType>::value,
836 std::is_empty<T>::value> = traits::sfinae>
inline 837 ArchiveType & processImpl(T
const &)
846 template <class T, traits::EnableIf<traits::has_invalid_input_versioning<T, ArchiveType>::value ||
847 (!traits::is_input_serializable<T, ArchiveType>::value &&
848 (!(
Flags & AllowEmptyClassElision) || ((
Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae>
inline 849 ArchiveType & processImpl(T
const &)
851 static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value != 0,
852 "cereal could not find any input serialization functions for the provided type and archive combination. \n\n " 853 "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " 854 "Serialize functions generally have the following signature: \n\n " 855 "template<class Archive> \n " 856 " void serialize(Archive & ar) \n " 858 " ar( member1, member2, member3 ); \n " 861 static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value < 2,
862 "cereal found more than one compatible input serialization function for the provided type and archive combination. \n\n " 863 "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " 864 "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n " 865 "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n " 866 "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
880 template <
class T>
inline 881 std::uint32_t loadClassVersion()
883 static const auto hash = std::type_index(
typeid(T)).hash_code();
884 auto lookupResult = itsVersionedTypes.find( hash );
886 if( lookupResult != itsVersionedTypes.end() )
887 return lookupResult->second;
890 std::uint32_t version;
892 process( make_nvp<ArchiveType>(
"cereal_class_version", version) );
893 itsVersionedTypes.emplace_hint( lookupResult, hash, version );
901 template <
class T, PROCESS_IF(member_versioned_serialize)>
inline 902 ArchiveType & processImpl(T & t)
904 const auto version = loadClassVersion<T>();
905 access::member_serialize(*
self, t, version);
911 template <
class T, PROCESS_IF(non_member_versioned_serialize)>
inline 912 ArchiveType & processImpl(T & t)
914 const auto version = loadClassVersion<T>();
921 template <
class T, PROCESS_IF(member_versioned_load)>
inline 922 ArchiveType & processImpl(T & t)
924 const auto version = loadClassVersion<T>();
925 access::member_load(*
self, t, version);
931 template <
class T, PROCESS_IF(non_member_versioned_load)>
inline 932 ArchiveType & processImpl(T & t)
934 const auto version = loadClassVersion<T>();
941 template <
class T, PROCESS_IF(member_versioned_load_minimal)>
inline 942 ArchiveType & processImpl(T & t)
945 const auto version = loadClassVersion<T>();
946 typename traits::has_member_versioned_save_minimal<T, OutArchiveType>::type value;
947 self->process(value);
948 access::member_load_minimal(*
self, t, value, version);
954 template <
class T, PROCESS_IF(non_member_versioned_load_minimal)>
inline 955 ArchiveType & processImpl(T & t)
958 const auto version = loadClassVersion<T>();
959 typename traits::has_non_member_versioned_save_minimal<T, OutArchiveType>::type value;
960 self->process(value);
968 ArchiveType *
const self;
971 std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
974 std::unordered_map<std::uint32_t, std::shared_ptr<void>> itsSharedPointerMap;
977 std::unordered_map<std::uint32_t, std::string> itsPolymorphicTypeMap;
980 std::unordered_map<std::size_t, std::uint32_t> itsVersionedTypes;
987 #endif // CEREAL_CEREAL_HPP_ The number of output serialization functions available.
Definition: traits.hpp:1071
A wrapper around size metadata.
Definition: helpers.hpp:273
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 this archive is not intended for loading.
Definition: cereal.hpp:263
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:362
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 this archive is intended for saving.
Definition: cereal.hpp:270
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:78
#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME
The serialization (save_minimal) function name to search for.
Definition: macros.hpp:106
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:328
Support common types - always included automatically.
Internal helper functionality.
Flags
Special flags for archives.
Definition: cereal.hpp:131
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:137
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:85
ArchiveType & operator &(T &&arg)
Serializes passed in data.
Definition: cereal.hpp:277
#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME
The deserialization (load_minimal) function name to search for.
Definition: macros.hpp:99
std::uint32_t registerSharedPointer(void const *addr)
Registers a shared pointer with the archive.
Definition: cereal.hpp:304
A wrapper around data that can be serialized in a binary fashion.
Definition: helpers.hpp:209
OutputArchive(ArchiveType *const derived)
Construct the output archive.
Definition: cereal.hpp:239
Definition: helpers.hpp:230
The base output archive class.
Definition: cereal.hpp:234
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:92
ArchiveType & operator()(Types &&... args)
Serializes all passed in data.
Definition: cereal.hpp:247
Definition: traits.hpp:1316
ArchiveType & operator<<(T &&arg)
Serializes passed in data.
Definition: cereal.hpp:288
Definition: traits.hpp:1123
A static, pre-execution object.
Definition: static_object.hpp:67
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