29 #ifndef CEREAL_CEREAL_HPP_ 30 #define CEREAL_CEREAL_HPP_ 32 #include <type_traits> 36 #include <unordered_map> 37 #include <unordered_set> 54 template <
class T>
inline 57 return {name.c_str(), std::forward<T>(value)};
63 template <
class T>
inline 66 return {name, std::forward<T>(value)};
72 #define CEREAL_NVP(T) ::cereal::make_nvp(#T, T) 80 template <
class T>
inline 83 return {std::forward<T>(data), size};
95 template <
class T>
inline 98 return {std::forward<T>(sz)};
148 template <
class T>
inline 151 return {std::forward<T>(value)};
161 template <
class Archive,
class T>
inline 168 template <
class Archive,
class T>
inline 185 enum Flags { AllowEmptyClassElision = 1 };
195 #define CEREAL_REGISTER_ARCHIVE(Archive) \ 196 namespace cereal { namespace detail { \ 197 template <class T, class BindingTag> \ 198 typename polymorphic_serialization_support<Archive, T>::type \ 199 instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \ 203 #if defined(__GNUC__) 205 #define CEREAL_UNUSED_FUNCTION 207 #define CEREAL_UNUSED_FUNCTION static void unused() { (void)version; } 261 #define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \ 262 namespace cereal { namespace detail { \ 263 template <> struct Version<TYPE> \ 265 static const std::uint32_t version; \ 266 static std::uint32_t registerVersion() \ 268 ::cereal::detail::StaticObject<Versions>::getInstance().mapping.emplace( \ 269 std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \ 270 return VERSION_NUMBER; \ 272 CEREAL_UNUSED_FUNCTION \ 274 const std::uint32_t Version<TYPE>::version = \ 275 Version<TYPE>::registerVersion(); \ 276 } } // end namespaces 295 template<
class ArchiveType, std::u
int32_t Flags = 0>
301 OutputArchive(ArchiveType *
const derived) : self(derived), itsCurrentPointerId(1), itsCurrentPolymorphicTypeId(1)
308 template <
class ... Types>
inline 311 self->process( std::forward<Types>( args )... );
319 for(
auto & deferment : itsDeferments )
346 template <
class T>
inline 349 self->process( std::forward<T>( arg ) );
357 template <
class T>
inline 360 self->process( std::forward<T>( arg ) );
377 if(addr == 0)
return 0;
379 auto id = itsSharedPointerMap.find( addr );
380 if(
id == itsSharedPointerMap.end() )
382 auto ptrId = itsCurrentPointerId++;
383 itsSharedPointerMap.insert( {addr, ptrId} );
384 return ptrId | detail::msb_32bit;
400 auto id = itsPolymorphicTypeMap.find( name );
401 if(
id == itsPolymorphicTypeMap.end() )
403 auto polyId = itsCurrentPolymorphicTypeId++;
404 itsPolymorphicTypeMap.insert( {name, polyId} );
405 return polyId | detail::msb_32bit;
413 template <
class T>
inline 414 void process( T && head )
417 self->processImpl( head );
422 template <
class T,
class ... Other>
inline 423 void process( T && head, Other && ... tail )
425 self->process( std::forward<T>( head ) );
426 self->process( std::forward<Other>( tail )... );
431 template <
class T>
inline 435 if(itsBaseClassSet.count(
id) == 0)
437 itsBaseClassSet.insert(
id);
438 self->processImpl( *b.base_ptr );
445 template <
class T>
inline 448 self->processImpl( *b.base_ptr );
452 std::vector<std::function<void(void)>> itsDeferments;
454 template <
class T>
inline 457 std::function<void(void)> deferment( [=](){
self->process( d.value ); } );
458 itsDeferments.emplace_back( std::move(deferment) );
470 #define PROCESS_IF(name) \ 471 traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \ 472 !traits::has_invalid_output_versioning<T, ArchiveType>::value, \ 473 (traits::is_output_serializable<T, ArchiveType>::value && \ 474 (traits::is_specialized_##name<T, ArchiveType>::value || \ 475 !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae 478 template <
class T, PROCESS_IF(member_serialize)>
inline 479 ArchiveType & processImpl(T
const & t)
481 access::member_serialize(*
self, const_cast<T &>(t));
486 template <
class T, PROCESS_IF(non_member_serialize)>
inline 487 ArchiveType & processImpl(T
const & t)
494 template <
class T, PROCESS_IF(member_save)>
inline 495 ArchiveType & processImpl(T
const & t)
497 access::member_save(*
self, t);
502 template <
class T, PROCESS_IF(non_member_save)>
inline 503 ArchiveType & processImpl(T
const & t)
510 template <
class T, PROCESS_IF(member_save_minimal)>
inline 511 ArchiveType & processImpl(T
const & t)
513 self->process( access::member_save_minimal(*
self, t) );
518 template <
class T, PROCESS_IF(non_member_save_minimal)>
inline 519 ArchiveType & processImpl(T
const & t)
528 std::is_empty<T>::value> = traits::sfinae>
inline 529 ArchiveType & processImpl(T
const &)
538 template <class T, traits::EnableIf<traits::has_invalid_output_versioning<T, ArchiveType>::value ||
540 (!(
Flags & AllowEmptyClassElision) || ((
Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae>
inline 541 ArchiveType & processImpl(T
const &)
544 "cereal could not find any output serialization functions for the provided type and archive combination. \n\n " 545 "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " 546 "Serialize functions generally have the following signature: \n\n " 547 "template<class Archive> \n " 548 " void serialize(Archive & ar) \n " 550 " ar( member1, member2, member3 ); \n " 554 "cereal found more than one compatible output serialization function for the provided type and archive combination. \n\n " 555 "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " 556 "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n " 557 "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n " 558 "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
568 template <
class T>
inline 569 std::uint32_t registerClassVersion()
571 static const auto hash = std::type_index(
typeid(T)).hash_code();
572 const auto insertResult = itsVersionedTypes.insert( hash );
577 if( insertResult.second )
578 process( make_nvp<ArchiveType>(
"cereal_class_version", version) );
585 template <
class T, PROCESS_IF(member_versioned_serialize)>
inline 586 ArchiveType & processImpl(T
const & t)
588 access::member_serialize(*
self, const_cast<T &>(t), registerClassVersion<T>());
594 template <
class T, PROCESS_IF(non_member_versioned_serialize)>
inline 595 ArchiveType & processImpl(T
const & t)
603 template <
class T, PROCESS_IF(member_versioned_save)>
inline 604 ArchiveType & processImpl(T
const & t)
606 access::member_save(*
self, t, registerClassVersion<T>());
612 template <
class T, PROCESS_IF(non_member_versioned_save)>
inline 613 ArchiveType & processImpl(T
const & t)
621 template <
class T, PROCESS_IF(member_versioned_save_minimal)>
inline 622 ArchiveType & processImpl(T
const & t)
624 self->process( access::member_save_minimal(*
self, t, registerClassVersion<T>()) );
630 template <
class T, PROCESS_IF(non_member_versioned_save_minimal)>
inline 631 ArchiveType & processImpl(T
const & t)
640 ArchiveType *
const self;
643 std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
646 std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap;
649 std::uint32_t itsCurrentPointerId;
652 std::unordered_map<char const *, std::uint32_t> itsPolymorphicTypeMap;
655 std::uint32_t itsCurrentPolymorphicTypeId;
658 std::unordered_set<size_type> itsVersionedTypes;
678 template<
class ArchiveType, std::u
int32_t Flags = 0>
687 itsSharedPointerMap(),
688 itsPolymorphicTypeMap(),
696 template <
class ... Types>
inline 699 process( std::forward<Types>( args )... );
707 for(
auto & deferment : itsDeferments )
734 template <
class T>
inline 737 self->process( std::forward<T>( arg ) );
745 template <
class T>
inline 748 self->process( std::forward<T>( arg ) );
764 if(
id == 0)
return std::shared_ptr<void>(
nullptr);
766 auto iter = itsSharedPointerMap.find(
id );
767 if(iter == itsSharedPointerMap.end())
768 throw Exception(
"Error while trying to deserialize a smart pointer. Could not find id " + std::to_string(
id));
782 std::uint32_t
const stripped_id =
id & ~detail::msb_32bit;
783 itsSharedPointerMap[stripped_id] = ptr;
795 auto name = itsPolymorphicTypeMap.find(
id );
796 if(name == itsPolymorphicTypeMap.end())
798 throw Exception(
"Error while trying to deserialize a polymorphic pointer. Could not find type id " + std::to_string(
id));
812 std::uint32_t
const stripped_id =
id & ~detail::msb_32bit;
813 itsPolymorphicTypeMap.insert( {stripped_id, name} );
818 template <
class T>
inline 819 void process( T && head )
822 self->processImpl( head );
827 template <
class T,
class ... Other>
inline 828 void process( T && head, Other && ... tail )
830 process( std::forward<T>( head ) );
831 process( std::forward<Other>( tail )... );
836 template <
class T>
inline 840 if(itsBaseClassSet.count(
id) == 0)
842 itsBaseClassSet.insert(
id);
843 self->processImpl( *b.base_ptr );
850 template <
class T>
inline 853 self->processImpl( *b.base_ptr );
857 std::vector<std::function<void(void)>> itsDeferments;
859 template <
class T>
inline 862 std::function<void(void)> deferment( [=](){
self->process( d.value ); } );
863 itsDeferments.emplace_back( std::move(deferment) );
875 #define PROCESS_IF(name) \ 876 traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \ 877 !traits::has_invalid_input_versioning<T, ArchiveType>::value, \ 878 (traits::is_input_serializable<T, ArchiveType>::value && \ 879 (traits::is_specialized_##name<T, ArchiveType>::value || \ 880 !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae 883 template <
class T, PROCESS_IF(member_serialize)>
inline 884 ArchiveType & processImpl(T & t)
886 access::member_serialize(*
self, t);
891 template <
class T, PROCESS_IF(non_member_serialize)>
inline 892 ArchiveType & processImpl(T & t)
899 template <
class T, PROCESS_IF(member_load)>
inline 900 ArchiveType & processImpl(T & t)
902 access::member_load(*
self, t);
907 template <
class T, PROCESS_IF(non_member_load)>
inline 908 ArchiveType & processImpl(T & t)
915 template <
class T, PROCESS_IF(member_load_minimal)>
inline 916 ArchiveType & processImpl(T & t)
918 using OutArchiveType =
typename traits::detail::get_output_from_input<ArchiveType>::type;
919 typename traits::has_member_save_minimal<T, OutArchiveType>::type value;
920 self->process( value );
921 access::member_load_minimal(*
self, t, value);
926 template <
class T, PROCESS_IF(non_member_load_minimal)>
inline 927 ArchiveType & processImpl(T & t)
929 using OutArchiveType =
typename traits::detail::get_output_from_input<ArchiveType>::type;
930 typename traits::has_non_member_save_minimal<T, OutArchiveType>::type value;
931 self->process( value );
938 !traits::is_input_serializable<T, ArchiveType>::value,
939 std::is_empty<T>::value> = traits::sfinae>
inline 940 ArchiveType & processImpl(T
const &)
949 template <class T, traits::EnableIf<traits::has_invalid_input_versioning<T, ArchiveType>::value ||
950 (!traits::is_input_serializable<T, ArchiveType>::value &&
951 (!(
Flags & AllowEmptyClassElision) || ((
Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae>
inline 952 ArchiveType & processImpl(T
const &)
954 static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value != 0,
955 "cereal could not find any input serialization functions for the provided type and archive combination. \n\n " 956 "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " 957 "Serialize functions generally have the following signature: \n\n " 958 "template<class Archive> \n " 959 " void serialize(Archive & ar) \n " 961 " ar( member1, member2, member3 ); \n " 964 static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value < 2,
965 "cereal found more than one compatible input serialization function for the provided type and archive combination. \n\n " 966 "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n " 967 "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n " 968 "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n " 969 "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
982 template <
class T>
inline 983 std::uint32_t loadClassVersion()
985 static const auto hash = std::type_index(
typeid(T)).hash_code();
986 auto lookupResult = itsVersionedTypes.find( hash );
988 if( lookupResult != itsVersionedTypes.end() )
989 return lookupResult->second;
992 std::uint32_t version;
994 process( make_nvp<ArchiveType>(
"cereal_class_version", version) );
995 itsVersionedTypes.emplace_hint( lookupResult, hash, version );
1003 template <
class T, PROCESS_IF(member_versioned_serialize)>
inline 1004 ArchiveType & processImpl(T & t)
1006 const auto version = loadClassVersion<T>();
1007 access::member_serialize(*
self, t, version);
1013 template <
class T, PROCESS_IF(non_member_versioned_serialize)>
inline 1014 ArchiveType & processImpl(T & t)
1016 const auto version = loadClassVersion<T>();
1023 template <
class T, PROCESS_IF(member_versioned_load)>
inline 1024 ArchiveType & processImpl(T & t)
1026 const auto version = loadClassVersion<T>();
1027 access::member_load(*
self, t, version);
1033 template <
class T, PROCESS_IF(non_member_versioned_load)>
inline 1034 ArchiveType & processImpl(T & t)
1036 const auto version = loadClassVersion<T>();
1043 template <
class T, PROCESS_IF(member_versioned_load_minimal)>
inline 1044 ArchiveType & processImpl(T & t)
1047 const auto version = loadClassVersion<T>();
1048 typename traits::has_member_versioned_save_minimal<T, OutArchiveType>::type value;
1049 self->process(value);
1050 access::member_load_minimal(*
self, t, value, version);
1056 template <
class T, PROCESS_IF(non_member_versioned_load_minimal)>
inline 1057 ArchiveType & processImpl(T & t)
1060 const auto version = loadClassVersion<T>();
1061 typename traits::has_non_member_versioned_save_minimal<T, OutArchiveType>::type value;
1062 self->process(value);
1070 ArchiveType *
const self;
1073 std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
1076 std::unordered_map<std::uint32_t, std::shared_ptr<void>> itsSharedPointerMap;
1079 std::unordered_map<std::uint32_t, std::string> itsPolymorphicTypeMap;
1082 std::unordered_map<std::size_t, std::uint32_t> itsVersionedTypes;
1089 #endif // CEREAL_CEREAL_HPP_
The number of output serialization functions available.
Definition: traits.hpp:1093
A wrapper around size metadata.
Definition: helpers.hpp:312
Casts a derived class to its virtual base class in a way that allows cereal to track inheritance...
Definition: base_class.hpp:188
std::false_type is_loading
Indicates this archive is not intended for loading.
Definition: cereal.hpp:333
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:401
NameValuePair< T > make_nvp(std::string const &name, T &&value)
Creates a name value pair.
Definition: cereal.hpp:55
std::true_type is_saving
Indicates this archive is intended for saving.
Definition: cereal.hpp:340
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:100
#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:162
SizeTag< T > make_size_tag(T &&sz)
Creates a size tag from some variable.
Definition: cereal.hpp:96
std::uint32_t registerPolymorphicType(char const *name)
Registers a polymorphic type name with the archive.
Definition: cereal.hpp:398
Support common types - always included automatically.
Internal helper functionality.
Flags
Special flags for archives.
Definition: cereal.hpp:185
static LockGuard lock()
Attempts to lock this static object for the current scope.
Definition: static_object.hpp:109
Definition: access.hpp:41
DeferredData< T > defer(T &&value)
Marks data for deferred serialization.
Definition: cereal.hpp:149
NameValuePair< T > make_nvp(const char *name, T &&value)
Creates a name value pair.
Definition: cereal.hpp:64
void serializeDeferments()
Serializes any data marked for deferment using defer.
Definition: cereal.hpp:317
For holding name value pairs.
Definition: helpers.hpp:139
Definition: traits.hpp:1111
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:347
#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:374
A wrapper around data that should be serialized after all non-deferred data.
Definition: helpers.hpp:232
A wrapper around data that can be serialized in a binary fashion.
Definition: helpers.hpp:211
OutputArchive(ArchiveType *const derived)
Construct the output archive.
Definition: cereal.hpp:301
Definition: helpers.hpp:269
The base output archive class.
Definition: cereal.hpp:296
#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:309
Definition: traits.hpp:1338
ArchiveType & operator<<(T &&arg)
Serializes passed in data.
Definition: cereal.hpp:358
Definition: traits.hpp:1145
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:81
void epilogue(Archive &, T const &)
Definition: cereal.hpp:169