30 #ifndef CEREAL_TYPES_POLYMORPHIC_HPP_ 31 #define CEREAL_TYPES_POLYMORPHIC_HPP_ 42 #define STATIC_CONSTEXPR static 44 #define STATIC_CONSTEXPR static constexpr 82 #define CEREAL_REGISTER_TYPE(T) \ 86 struct binding_name<T> \ 88 STATIC_CONSTEXPR char const * name() { return #T; } \ 91 CEREAL_BIND_TO_ARCHIVES(T) 99 #define CEREAL_REGISTER_TYPE_WITH_NAME(T, Name) \ 103 struct binding_name<T> \ 104 { STATIC_CONSTEXPR char const * name() { return Name; } }; \ 106 CEREAL_BIND_TO_ARCHIVES(T) 134 #define CEREAL_REGISTER_DYNAMIC_INIT(LibName) \ 137 void CEREAL_DLL_EXPORT dynamic_init_dummy_##LibName() {} \ 147 #define CEREAL_FORCE_DYNAMIC_INIT(LibName) \ 150 void dynamic_init_dummy_##LibName(); \ 153 void dynamic_init_##LibName() \ 155 ::cereal::detail::dynamic_init_dummy_##LibName(); \ 165 namespace polymorphic_detail
169 #define UNREGISTERED_POLYMORPHIC_EXCEPTION(LoadSave, Name) \ 170 throw cereal::Exception("Trying to " #LoadSave " an unregistered polymorphic type (" + Name + ").\n" \ 171 "Make sure your type is registered with CEREAL_REGISTER_TYPE and that the archive " \ 172 "you are using was included (and registered with CEREAL_REGISTER_ARCHIVE) prior to calling CEREAL_REGISTER_TYPE.\n" \ 173 "If your type is already registered and you still see this error, you may need to use CEREAL_REGISTER_DYNAMIC_INIT."); 177 template<
class Archive>
inline 178 typename ::cereal::detail::InputBindingMap<Archive>::Serializers
getInputBinding(Archive & ar, std::uint32_t
const nameid)
183 typename ::cereal::detail::InputBindingMap<Archive>::Serializers emptySerializers;
184 emptySerializers.shared_ptr = [](
void*, std::shared_ptr<void> & ptr) { ptr.reset(); };
185 emptySerializers.unique_ptr = [](
void*, std::unique_ptr<void, ::cereal::detail::EmptyDeleter<void>> & ptr) { ptr.reset(
nullptr ); };
186 return emptySerializers;
190 if(nameid & detail::msb_32bit)
193 ar.registerPolymorphicName(nameid, name);
196 name = ar.getPolymorphicName(nameid);
200 auto binding = bindingMap.find(name);
201 if(binding == bindingMap.end())
203 return binding->second;
213 template<
class Archive,
class T>
inline 214 typename std::enable_if<(traits::is_default_constructible<T>::value
216 && !std::is_abstract<T>::value,
bool>::type
219 if(nameid & detail::msb2_32bit)
221 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
231 template<
class Archive,
class T,
class D>
inline 232 typename std::enable_if<(traits::is_default_constructible<T>::value
234 && !std::is_abstract<T>::value,
bool>::type
237 if(nameid & detail::msb2_32bit)
239 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
251 template<
class Archive,
class T>
inline 252 typename std::enable_if<(!traits::is_default_constructible<T>::value
254 || std::is_abstract<T>::value,
bool>::type
257 if(nameid & detail::msb2_32bit)
258 throw cereal::Exception(
"Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function");
268 template<
class Archive,
class T,
class D>
inline 269 typename std::enable_if<(!traits::is_default_constructible<T>::value
271 || std::is_abstract<T>::value,
bool>::type
274 if(nameid & detail::msb2_32bit)
275 throw cereal::Exception(
"Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function");
284 template <
class Archive,
class T>
inline 285 typename std::enable_if<std::is_polymorphic<T>::value && std::is_abstract<T>::value,
void>::type
291 ar(
CEREAL_NVP_(
"polymorphic_id", std::uint32_t(0)) );
295 std::type_info
const & ptrinfo =
typeid(*ptr.get());
302 auto binding = bindingMap.find(std::type_index(ptrinfo));
303 if(binding == bindingMap.end())
306 binding->second.shared_ptr(&ar, ptr.get());
310 template <
class Archive,
class T>
inline 311 typename std::enable_if<std::is_polymorphic<T>::value && !std::is_abstract<T>::value,
void>::type
317 ar(
CEREAL_NVP_(
"polymorphic_id", std::uint32_t(0)) );
321 std::type_info
const & ptrinfo =
typeid(*ptr.get());
322 static std::type_info
const & tinfo =
typeid(T);
328 ar(
CEREAL_NVP_(
"polymorphic_id", detail::msb2_32bit) );
330 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
337 auto binding = bindingMap.find(std::type_index(ptrinfo));
338 if(binding == bindingMap.end())
341 binding->second.shared_ptr(&ar, ptr.get());
345 template <
class Archive,
class T>
inline 346 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
349 std::uint32_t nameid;
353 if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
356 auto binding = polymorphic_detail::getInputBinding(ar, nameid);
357 std::shared_ptr<void> result;
358 binding.shared_ptr(&ar, result);
359 ptr = std::static_pointer_cast<T>(result);
363 template <
class Archive,
class T>
inline 364 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
367 auto const sptr = ptr.lock();
372 template <
class Archive,
class T>
inline 373 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
376 std::shared_ptr<T> sptr;
382 template <
class Archive,
class T,
class D>
inline 383 typename std::enable_if<std::is_polymorphic<T>::value && std::is_abstract<T>::value,
void>::type
389 ar(
CEREAL_NVP_(
"polymorphic_id", std::uint32_t(0)) );
393 std::type_info
const & ptrinfo =
typeid(*ptr.get());
400 auto binding = bindingMap.find(std::type_index(ptrinfo));
401 if(binding == bindingMap.end())
404 binding->second.unique_ptr(&ar, ptr.get());
408 template <
class Archive,
class T,
class D>
inline 409 typename std::enable_if<std::is_polymorphic<T>::value && !std::is_abstract<T>::value,
void>::type
415 ar(
CEREAL_NVP_(
"polymorphic_id", std::uint32_t(0)) );
419 std::type_info
const & ptrinfo =
typeid(*ptr.get());
420 static std::type_info
const & tinfo =
typeid(T);
426 ar(
CEREAL_NVP_(
"polymorphic_id", detail::msb2_32bit) );
428 ar(
CEREAL_NVP_(
"ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
435 auto binding = bindingMap.find(std::type_index(ptrinfo));
436 if(binding == bindingMap.end())
439 binding->second.unique_ptr(&ar, ptr.get());
443 template <
class Archive,
class T,
class D>
inline 444 typename std::enable_if<std::is_polymorphic<T>::value,
void>::type
447 std::uint32_t nameid;
451 if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
454 auto binding = polymorphic_detail::getInputBinding(ar, nameid);
455 std::unique_ptr<void, ::cereal::detail::EmptyDeleter<void>> result;
456 binding.unique_ptr(&ar, result);
457 ptr.reset(static_cast<T*>(result.release()));
460 #undef UNREGISTERED_POLYMORPHIC_EXCEPTION 462 #endif // CEREAL_TYPES_POLYMORPHIC_HPP_ Has either a member or non member allocate.
Definition: traits.hpp:1192
#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:217
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:178
#define UNREGISTERED_POLYMORPHIC_EXCEPTION(LoadSave, Name)
Error message used for unregistered polymorphic types.
Definition: polymorphic.hpp:169
Internal type trait support.
Internal helper functionality.
Definition: access.hpp:39
Main cereal functionality.
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:58
Internal polymorphism support.
#define CEREAL_SAVE_FUNCTION_NAME
The serialization (save) function name to search for.
Definition: macros.hpp:65
A static, pre-execution object.
Definition: static_object.hpp:61
Support for types found in <memory>
An exception class thrown when things go wrong at runtime.
Definition: helpers.hpp:48