30 #ifndef CEREAL_TYPES_POLYMORPHIC_HPP_ 31 #define CEREAL_TYPES_POLYMORPHIC_HPP_ 42 #define CEREAL_STATIC_CONSTEXPR static 44 #define CEREAL_STATIC_CONSTEXPR static constexpr 82 #define CEREAL_REGISTER_TYPE(...) \ 86 struct binding_name<__VA_ARGS__> \ 88 CEREAL_STATIC_CONSTEXPR char const * name() { return #__VA_ARGS__; } \ 91 CEREAL_BIND_TO_ARCHIVES(__VA_ARGS__) 99 #define CEREAL_REGISTER_TYPE_WITH_NAME(T, Name) \ 103 struct binding_name<T> \ 104 { CEREAL_STATIC_CONSTEXPR char const * name() { return Name; } }; \ 106 CEREAL_BIND_TO_ARCHIVES(T) 121 #define CEREAL_REGISTER_POLYMORPHIC_RELATION(Base, Derived) \ 125 struct PolymorphicRelation<Base, Derived> \ 126 { static void bind() { RegisterPolymorphicCaster<Base, Derived>::bind(); } }; \ 155 #define CEREAL_REGISTER_DYNAMIC_INIT(LibName) \ 158 void CEREAL_DLL_EXPORT dynamic_init_dummy_##LibName() {} \ 168 #define CEREAL_FORCE_DYNAMIC_INIT(LibName) \ 171 void dynamic_init_dummy_##LibName(); \ 174 void dynamic_init_##LibName() \ 176 ::cereal::detail::dynamic_init_dummy_##LibName(); \ 182 namespace polymorphic_detail
186 #define UNREGISTERED_POLYMORPHIC_EXCEPTION(LoadSave, Name) \ 187 throw cereal::Exception("Trying to " #LoadSave " an unregistered polymorphic type (" + Name + ").\n" \ 188 "Make sure your type is registered with CEREAL_REGISTER_TYPE and that the archive " \ 189 "you are using was included (and registered with CEREAL_REGISTER_ARCHIVE) prior to calling CEREAL_REGISTER_TYPE.\n" \ 190 "If your type is already registered and you still see this error, you may need to use CEREAL_REGISTER_DYNAMIC_INIT."); 194 template<
class Archive>
inline 195 typename ::cereal::detail::InputBindingMap<Archive>::Serializers
getInputBinding(Archive & ar, std::uint32_t
const nameid)
200 typename ::cereal::detail::InputBindingMap<Archive>::Serializers emptySerializers;
201 emptySerializers.shared_ptr = [](
void*, std::shared_ptr<void> & ptr, std::type_info
const &) { ptr.reset(); };
202 emptySerializers.unique_ptr = [](
void*, std::unique_ptr<void, ::cereal::detail::EmptyDeleter<void>> & ptr, std::type_info
const &) { ptr.reset(
nullptr ); };
203 return emptySerializers;
207 if(nameid & detail::msb_32bit)
209 ar(
CEREAL_NVP_(
"polymorphic_name", detail::make_polymorphic_key_tag(name)) );
210 ar.registerPolymorphicName(nameid, name);
213 name = ar.getPolymorphicName(nameid);
217 auto binding = bindingMap.find(name);
218 if(binding == bindingMap.end())
220 return binding->second;
224 template <
class Archive>
inline 227 return bindingMap.end() != bindingMap.find(name);
237 template<
class Archive,
class T>
inline 238 typename std::enable_if<(traits::is_default_constructible<T>::value
240 && !std::is_abstract<T>::value,
bool>::type
243 if(nameid & detail::msb2_32bit)
245 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
255 template<
class Archive,
class T,
class D>
inline 256 typename std::enable_if<(traits::is_default_constructible<T>::value
258 && !std::is_abstract<T>::value,
bool>::type
261 if(nameid & detail::msb2_32bit)
263 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
275 template<
class Archive,
class T>
inline 276 typename std::enable_if<(!traits::is_default_constructible<T>::value
278 || std::is_abstract<T>::value,
bool>::type
281 if(nameid & detail::msb2_32bit)
282 throw cereal::Exception(
"Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function");
292 template<
class Archive,
class T,
class D>
inline 293 typename std::enable_if<(!traits::is_default_constructible<T>::value
295 || std::is_abstract<T>::value,
bool>::type
298 if(nameid & detail::msb2_32bit)
299 throw cereal::Exception(
"Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function");
308 template <
class Archive,
class T>
inline 309 typename std::enable_if<std::is_polymorphic<T>::value && std::is_abstract<T>::value,
void>::type
315 ar(
CEREAL_NVP_(
"polymorphic_id", detail::make_polymorphic_id_tag(std::uint32_t(0))) );
319 std::type_info
const & ptrinfo =
typeid(*ptr.get());
320 static std::type_info
const & tinfo =
typeid(T);
327 auto binding = bindingMap.find(std::type_index(ptrinfo));
328 if(binding == bindingMap.end())
331 binding->second.shared_ptr(&ar, ptr.get(), tinfo);
335 template <
class Archive,
class T>
inline 336 typename std::enable_if<std::is_polymorphic<T>::value && !std::is_abstract<T>::value,
void>::type
342 ar(
CEREAL_NVP_(
"polymorphic_id", detail::make_polymorphic_id_tag(std::uint32_t(0))) );
346 std::type_info
const & ptrinfo =
typeid(*ptr.get());
347 static std::type_info
const & tinfo =
typeid(T);
353 ar(
CEREAL_NVP_(
"polymorphic_id", detail::make_polymorphic_id_tag(detail::msb2_32bit)) );
355 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
362 auto binding = bindingMap.find(std::type_index(ptrinfo));
363 if(binding == bindingMap.end())
366 binding->second.shared_ptr(&ar, ptr.get(), tinfo);
370 template <
class Archive,
class T>
inline 371 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
374 std::uint32_t nameid;
375 ar(
CEREAL_NVP_(
"polymorphic_id", detail::make_polymorphic_id_tag(nameid)) );
378 if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
381 auto binding = polymorphic_detail::getInputBinding(ar, nameid);
382 std::shared_ptr<void> result;
383 binding.shared_ptr(&ar, result,
typeid(T));
384 ptr = std::static_pointer_cast<T>(result);
388 template <
class Archive,
class T>
inline 389 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
392 auto const sptr = ptr.lock();
397 template <
class Archive,
class T>
inline 398 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
401 std::shared_ptr<T> sptr;
407 template <
class Archive,
class T,
class D>
inline 408 typename std::enable_if<std::is_polymorphic<T>::value && std::is_abstract<T>::value,
void>::type
414 ar(
CEREAL_NVP_(
"polymorphic_id", detail::make_polymorphic_id_tag(std::uint32_t(0))) );
418 std::type_info
const & ptrinfo =
typeid(*ptr.get());
419 static std::type_info
const & tinfo =
typeid(T);
426 auto binding = bindingMap.find(std::type_index(ptrinfo));
427 if(binding == bindingMap.end())
430 binding->second.unique_ptr(&ar, ptr.get(), tinfo);
434 template <
class Archive,
class T,
class D>
inline 435 typename std::enable_if<std::is_polymorphic<T>::value && !std::is_abstract<T>::value,
void>::type
441 ar(
CEREAL_NVP_(
"polymorphic_id", detail::make_polymorphic_id_tag(std::uint32_t(0))) );
445 std::type_info
const & ptrinfo =
typeid(*ptr.get());
446 static std::type_info
const & tinfo =
typeid(T);
452 ar(
CEREAL_NVP_(
"polymorphic_id", detail::make_polymorphic_id_tag(detail::msb2_32bit)) );
454 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
461 auto binding = bindingMap.find(std::type_index(ptrinfo));
462 if(binding == bindingMap.end())
465 binding->second.unique_ptr(&ar, ptr.get(), tinfo);
469 template <
class Archive,
class T,
class D>
inline 470 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
473 std::uint32_t nameid;
474 ar(
CEREAL_NVP_(
"polymorphic_id", detail::make_polymorphic_id_tag(nameid)) );
477 if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
480 auto binding = polymorphic_detail::getInputBinding(ar, nameid);
481 std::unique_ptr<void, ::cereal::detail::EmptyDeleter<void>> result;
482 binding.unique_ptr(&ar, result,
typeid(T));
483 ptr.reset(static_cast<T*>(result.release()));
486 #undef UNREGISTERED_POLYMORPHIC_EXCEPTION 488 #endif // CEREAL_TYPES_POLYMORPHIC_HPP_ Non member load and construct check.
Definition: traits.hpp:917
#define CEREAL_NVP_(name, value)
Convenience for creating a templated NVP.
Definition: helpers.hpp:197
std::enable_if<(traits::is_default_constructible< T >::value||traits::has_load_and_construct< T, Archive >::value) &&!std::is_abstract< T >::value, bool >::type serialize_wrapper(Archive &ar, std::shared_ptr< T > &ptr, std::uint32_t const nameid)
Serialize a shared_ptr if the 2nd msb in the nameid is set, and if we can actually construct the poin...
Definition: polymorphic.hpp:241
typename ::cereal::detail::InputBindingMap< Archive >::Serializers getInputBinding(Archive &ar, std::uint32_t const nameid)
Get an input binding from the given archive by deserializing the type meta data.
Definition: polymorphic.hpp:195
#define UNREGISTERED_POLYMORPHIC_EXCEPTION(LoadSave, Name)
Error message used for unregistered polymorphic types.
Definition: polymorphic.hpp:186
Internal type trait support.
Internal helper functionality.
bool hasPolymorphicBinding(const std::string &name)
Returns if given name was registered for polymorphic loading.
Definition: polymorphic.hpp:225
Definition: access.hpp:40
Main cereal functionality.
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:71
Internal polymorphism support.
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:78
A static, pre-execution object.
Definition: static_object.hpp:67
Support for types found in <memory>
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48