30#ifndef CEREAL_TYPES_POLYMORPHIC_HPP_
31#define CEREAL_TYPES_POLYMORPHIC_HPP_
41#if defined(_MSC_VER) && _MSC_VER < 1916
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 CEREAL_DLL_EXPORT dynamic_init_dummy_##LibName(); \
175 struct dynamic_init_##LibName { \
176 dynamic_init_##LibName() { \
177 ::cereal::detail::dynamic_init_dummy_##LibName(); \
179 } dynamic_init_instance_##LibName; \
184 namespace polymorphic_detail
188 #define UNREGISTERED_POLYMORPHIC_EXCEPTION(LoadSave, Name) \
189 throw cereal::Exception("Trying to " #LoadSave " an unregistered polymorphic type (" + Name + ").\n" \
190 "Make sure your type is registered with CEREAL_REGISTER_TYPE and that the archive " \
191 "you are using was included (and registered with CEREAL_REGISTER_ARCHIVE) prior to calling CEREAL_REGISTER_TYPE.\n" \
192 "If your type is already registered and you still see this error, you may need to use CEREAL_REGISTER_DYNAMIC_INIT.");
196 template<
class Archive>
inline
197 typename ::cereal::detail::InputBindingMap<Archive>::Serializers
getInputBinding(Archive & ar, std::uint32_t
const nameid)
202 typename ::cereal::detail::InputBindingMap<Archive>::Serializers emptySerializers;
203 emptySerializers.shared_ptr = [](
void*, std::shared_ptr<void> & ptr, std::type_info
const &) { ptr.reset(); };
204 emptySerializers.unique_ptr = [](
void*, std::unique_ptr<void, ::cereal::detail::EmptyDeleter<void>> & ptr, std::type_info
const &) { ptr.reset(
nullptr ); };
205 return emptySerializers;
209 if(nameid & detail::msb_32bit)
212 ar.registerPolymorphicName(nameid, name);
215 name = ar.getPolymorphicName(nameid);
219 auto binding = bindingMap.find(name);
220 if(binding == bindingMap.end())
222 return binding->second;
232 template<
class Archive,
class T>
inline
235 && !std::is_abstract<T>::value,
bool>::type
238 if(nameid & detail::msb2_32bit)
240 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
250 template<
class Archive,
class T,
class D>
inline
253 && !std::is_abstract<T>::value,
bool>::type
256 if(nameid & detail::msb2_32bit)
258 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
270 template<
class Archive,
class T>
inline
273 || std::is_abstract<T>::value,
bool>::type
276 if(nameid & detail::msb2_32bit)
277 throw cereal::Exception(
"Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function");
287 template<
class Archive,
class T,
class D>
inline
290 || std::is_abstract<T>::value,
bool>::type
293 if(nameid & detail::msb2_32bit)
294 throw cereal::Exception(
"Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function");
303 template <
class Archive,
class T>
inline
304 typename std::enable_if<std::is_polymorphic<T>::value && std::is_abstract<T>::value,
void>::type
310 ar(
CEREAL_NVP_(
"polymorphic_id", std::uint32_t(0)) );
314 std::type_info
const & ptrinfo =
typeid(*ptr.get());
315 static std::type_info
const & tinfo =
typeid(T);
322 auto binding = bindingMap.find(std::type_index(ptrinfo));
323 if(binding == bindingMap.end())
326 binding->second.shared_ptr(&ar, ptr.get(), tinfo);
330 template <
class Archive,
class T>
inline
331 typename std::enable_if<std::is_polymorphic<T>::value && !std::is_abstract<T>::value,
void>::type
337 ar(
CEREAL_NVP_(
"polymorphic_id", std::uint32_t(0)) );
341 std::type_info
const & ptrinfo =
typeid(*ptr.get());
342 static std::type_info
const & tinfo =
typeid(T);
348 ar(
CEREAL_NVP_(
"polymorphic_id", detail::msb2_32bit) );
350 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
357 auto binding = bindingMap.find(std::type_index(ptrinfo));
358 if(binding == bindingMap.end())
361 binding->second.shared_ptr(&ar, ptr.get(), tinfo);
365 template <
class Archive,
class T>
inline
366 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
369 std::uint32_t nameid;
373 if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
376 auto binding = polymorphic_detail::getInputBinding(ar, nameid);
377 std::shared_ptr<void> result;
378 binding.shared_ptr(&ar, result,
typeid(T));
379 ptr = std::static_pointer_cast<T>(result);
383 template <
class Archive,
class T>
inline
384 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
387 auto const sptr = ptr.lock();
392 template <
class Archive,
class T>
inline
393 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
396 std::shared_ptr<T> sptr;
402 template <
class Archive,
class T,
class D>
inline
403 typename std::enable_if<std::is_polymorphic<T>::value && std::is_abstract<T>::value,
void>::type
409 ar(
CEREAL_NVP_(
"polymorphic_id", std::uint32_t(0)) );
413 std::type_info
const & ptrinfo =
typeid(*ptr.get());
414 static std::type_info
const & tinfo =
typeid(T);
421 auto binding = bindingMap.find(std::type_index(ptrinfo));
422 if(binding == bindingMap.end())
425 binding->second.unique_ptr(&ar, ptr.get(), tinfo);
429 template <
class Archive,
class T,
class D>
inline
430 typename std::enable_if<std::is_polymorphic<T>::value && !std::is_abstract<T>::value,
void>::type
436 ar(
CEREAL_NVP_(
"polymorphic_id", std::uint32_t(0)) );
440 std::type_info
const & ptrinfo =
typeid(*ptr.get());
441 static std::type_info
const & tinfo =
typeid(T);
447 ar(
CEREAL_NVP_(
"polymorphic_id", detail::msb2_32bit) );
449 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
456 auto binding = bindingMap.find(std::type_index(ptrinfo));
457 if(binding == bindingMap.end())
460 binding->second.unique_ptr(&ar, ptr.get(), tinfo);
464 template <
class Archive,
class T,
class D>
inline
465 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
468 std::uint32_t nameid;
472 if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
475 auto binding = polymorphic_detail::getInputBinding(ar, nameid);
476 std::unique_ptr<void, ::cereal::detail::EmptyDeleter<void>> result;
477 binding.unique_ptr(&ar, result,
typeid(T));
478 ptr.reset(
static_cast<T*
>(result.release()));
481 #undef UNREGISTERED_POLYMORPHIC_EXCEPTION
Main cereal functionality.
A static, pre-execution object.
Definition: static_object.hpp:68
Internal helper functionality.
#define CEREAL_NVP_(name, value)
Convenience for creating a templated NVP.
Definition: helpers.hpp:201
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:85
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:92
Support for types found in <memory>
#define UNREGISTERED_POLYMORPHIC_EXCEPTION(LoadSave, Name)
Error message used for unregistered polymorphic types.
Definition: polymorphic.hpp:188
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:236
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:197
Internal polymorphism support.
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:49
Non member load and construct check.
Definition: traits.hpp:942
Determines whether the class T can be default constructed by cereal::access.
Definition: traits.hpp:1255
Internal type trait support.