cereal
A C++11 library for serialization
polymorphic_impl.hpp
Go to the documentation of this file.
1 
4 /*
5  Copyright (c) 2014, Randolph Voorhies, Shane Grant
6  All rights reserved.
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions are met:
10  * Redistributions of source code must retain the above copyright
11  notice, this list of conditions and the following disclaimer.
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in the
14  documentation and/or other materials provided with the distribution.
15  * Neither the name of cereal nor the
16  names of its contributors may be used to endorse or promote products
17  derived from this software without specific prior written permission.
18 
19  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
23  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 
31 /* This code is heavily inspired by the boost serialization implementation by the following authors
32 
33  (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
34  Use, modification and distribution is subject to the Boost Software
35  License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt)
36 
37  See http://www.boost.org for updates, documentation, and revision history.
38 
39  (C) Copyright 2006 David Abrahams - http://www.boost.org.
40 
41  See /boost/serialization/export.hpp, /boost/archive/detail/register_archive.hpp,
42  and /boost/serialization/void_cast.hpp for their implementation. Additional details
43  found in other files split across serialization and archive.
44 */
45 #ifndef CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
46 #define CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
47 
50 #include "cereal/types/memory.hpp"
51 #include "cereal/types/string.hpp"
52 #include <functional>
53 #include <typeindex>
54 #include <map>
55 #include <limits>
56 #include <set>
57 #include <stack>
58 
60 
64 #define CEREAL_BIND_TO_ARCHIVES(...) \
65  namespace cereal { \
66  namespace detail { \
67  template<> \
68  struct init_binding<__VA_ARGS__> { \
69  static bind_to_archives<__VA_ARGS__> const & b; \
70  static void unused() { (void)b; } \
71  }; \
72  bind_to_archives<__VA_ARGS__> const & init_binding<__VA_ARGS__>::b = \
73  ::cereal::detail::StaticObject< \
74  bind_to_archives<__VA_ARGS__> \
75  >::getInstance().bind(); \
76  }} /* end namespaces */
77 
78 namespace cereal
79 {
80  /* Polymorphic casting support */
81  namespace detail
82  {
84 
97  {
98  PolymorphicCaster() = default;
99  PolymorphicCaster( const PolymorphicCaster & ) = default;
100  PolymorphicCaster & operator=( const PolymorphicCaster & ) = default;
102  PolymorphicCaster & operator=( PolymorphicCaster && ) CEREAL_NOEXCEPT { return *this; }
103  virtual ~PolymorphicCaster() CEREAL_NOEXCEPT = default;
104 
106  virtual void const * downcast( void const * const ptr ) const = 0;
108  virtual void * upcast( void * const ptr ) const = 0;
110  virtual std::shared_ptr<void> upcast( std::shared_ptr<void> const & ptr ) const = 0;
111  };
112 
114 
117  {
119  std::map<std::type_index, std::map<std::type_index, std::vector<PolymorphicCaster const*>>> map;
120 
121  std::multimap<std::type_index, std::type_index> reverseMap;
122 
124  #define UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(LoadSave) \
125  throw cereal::Exception("Trying to " #LoadSave " a registered polymorphic type with an unregistered polymorphic cast.\n" \
126  "Could not find a path to a base class (" + util::demangle(baseInfo.name()) + ") for type: " + ::cereal::util::demangledName<Derived>() + "\n" \
127  "Make sure you either serialize the base class at some point via cereal::base_class or cereal::virtual_base_class.\n" \
128  "Alternatively, manually register the association with CEREAL_REGISTER_POLYMORPHIC_RELATION.");
129 
131 
133  static bool exists( std::type_index const & baseIndex, std::type_index const & derivedIndex )
134  {
135  // First phase of lookup - match base type index
136  auto const & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
137  auto baseIter = baseMap.find( baseIndex );
138  if (baseIter == baseMap.end())
139  return false;
140 
141  // Second phase - find a match from base to derived
142  auto & derivedMap = baseIter->second;
143  auto derivedIter = derivedMap.find( derivedIndex );
144  if (derivedIter == derivedMap.end())
145  return false;
146 
147  return true;
148  }
149 
151 
155  template <class F> inline
156  static std::vector<PolymorphicCaster const *> const & lookup( std::type_index const & baseIndex, std::type_index const & derivedIndex, F && exceptionFunc )
157  {
158  // First phase of lookup - match base type index
159  auto const & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
160  auto baseIter = baseMap.find( baseIndex );
161  if( baseIter == baseMap.end() )
162  exceptionFunc();
163 
164  // Second phase - find a match from base to derived
165  auto & derivedMap = baseIter->second;
166  auto derivedIter = derivedMap.find( derivedIndex );
167  if( derivedIter == derivedMap.end() )
168  exceptionFunc();
169 
170  return derivedIter->second;
171  }
172 
174  template <class Derived> inline
175  static const Derived * downcast( const void * dptr, std::type_info const & baseInfo )
176  {
177  auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(save) } );
178 
179  for( auto const * map : mapping )
180  dptr = map->downcast( dptr );
181 
182  return static_cast<Derived const *>( dptr );
183  }
184 
186 
188  template <class Derived> inline
189  static void * upcast( Derived * const dptr, std::type_info const & baseInfo )
190  {
191  auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } );
192 
193  void * uptr = dptr;
194  for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter )
195  uptr = (*mIter)->upcast( uptr );
196 
197  return uptr;
198  }
199 
201  template <class Derived> inline
202  static std::shared_ptr<void> upcast( std::shared_ptr<Derived> const & dptr, std::type_info const & baseInfo )
203  {
204  auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } );
205 
206  std::shared_ptr<void> uptr = dptr;
207  for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter )
208  uptr = (*mIter)->upcast( uptr );
209 
210  return uptr;
211  }
212 
213  #undef UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION
214  };
215 
217  template <class Base, class Derived>
219  {
221 
225  {
226  const auto baseKey = std::type_index(typeid(Base));
227  const auto derivedKey = std::type_index(typeid(Derived));
228 
229  // First insert the relation Base->Derived
230  const auto lock = StaticObject<PolymorphicCasters>::lock();
231  auto & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
232  auto lb = baseMap.lower_bound(baseKey);
233 
234  {
235  auto & derivedMap = baseMap.insert( lb, {baseKey, {}} )->second;
236  auto lbd = derivedMap.lower_bound(derivedKey);
237  auto & derivedVec = derivedMap.insert( lbd, { std::move(derivedKey), {}} )->second;
238  derivedVec.push_back( this );
239  }
240 
241  // Insert reverse relation Derived->Base
242  auto & reverseMap = StaticObject<PolymorphicCasters>::getInstance().reverseMap;
243  reverseMap.insert( {derivedKey, baseKey} );
244 
245  // Find all chainable unregistered relations
246  /* The strategy here is to process only the nodes in the class hierarchy graph that have been
247  affected by the new insertion. The aglorithm iteratively processes a node an ensures that it
248  is updated with all new shortest length paths. It then rocesses the parents of the active node,
249  with the knowledge that all children have already been processed.
250 
251  Note that for the following, we'll use the nomenclature of parent and child to not confuse with
252  the inserted base derived relationship */
253  {
254  // Checks whether there is a path from parent->child and returns a <dist, path> pair
255  // dist is set to MAX if the path does not exist
256  auto checkRelation = [](std::type_index const & parentInfo, std::type_index const & childInfo) ->
257  std::pair<size_t, std::vector<PolymorphicCaster const *>>
258  {
259  if( PolymorphicCasters::exists( parentInfo, childInfo ) )
260  {
261  auto const & path = PolymorphicCasters::lookup( parentInfo, childInfo, [](){} );
262  return {path.size(), path};
263  }
264  else
265  return {std::numeric_limits<size_t>::max(), {}};
266  };
267 
268  std::stack<std::type_index> parentStack; // Holds the parent nodes to be processed
269  std::set<std::type_index> dirtySet; // Marks child nodes that have been changed
270  std::set<std::type_index> processedParents; // Marks parent nodes that have been processed
271 
272  // Begin processing the base key and mark derived as dirty
273  parentStack.push( baseKey );
274  dirtySet.insert( derivedKey );
275 
276  while( !parentStack.empty() )
277  {
278  using Relations = std::multimap<std::type_index, std::pair<std::type_index, std::vector<PolymorphicCaster const *>>>;
279  Relations unregisteredRelations; // Defer insertions until after main loop to prevent iterator invalidation
280 
281  const auto parent = parentStack.top();
282  parentStack.pop();
283 
284  // Update paths to all children marked dirty
285  for( auto const & childPair : baseMap[parent] )
286  {
287  const auto child = childPair.first;
288  if( dirtySet.count( child ) && baseMap.count( child ) )
289  {
290  auto parentChildPath = checkRelation( parent, child );
291 
292  // Search all paths from the child to its own children (finalChild),
293  // looking for a shorter parth from parent to finalChild
294  for( auto const & finalChildPair : baseMap[child] )
295  {
296  const auto finalChild = finalChildPair.first;
297 
298  auto parentFinalChildPath = checkRelation( parent, finalChild );
299  auto childFinalChildPath = checkRelation( child, finalChild );
300 
301  const size_t newLength = 1u + parentChildPath.first;
302 
303  if( newLength < parentFinalChildPath.first )
304  {
305  std::vector<PolymorphicCaster const *> path = parentChildPath.second;
306  path.insert( path.end(), childFinalChildPath.second.begin(), childFinalChildPath.second.end() );
307 
308  // Check to see if we have a previous uncommitted path in unregisteredRelations
309  // that is shorter. If so, ignore this path
310  auto hintRange = unregisteredRelations.equal_range( parent );
311  auto hint = hintRange.first;
312  for( ; hint != hintRange.second; ++hint )
313  if( hint->second.first == finalChild )
314  break;
315 
316  const bool uncommittedExists = hint != unregisteredRelations.end();
317  if( uncommittedExists && (hint->second.second.size() <= newLength) )
318  continue;
319 
320  auto newPath = std::pair<std::type_index, std::vector<PolymorphicCaster const *>>{finalChild, std::move(path)};
321 
322  // Insert the new path if it doesn't exist, otherwise this will just lookup where to do the
323  // replacement
324  #ifdef CEREAL_OLDER_GCC
325  auto old = unregisteredRelations.insert( hint, std::make_pair(parent, newPath) );
326  #else // NOT CEREAL_OLDER_GCC
327  auto old = unregisteredRelations.emplace_hint( hint, parent, newPath );
328  #endif // NOT CEREAL_OLDER_GCC
329 
330  // If there was an uncommitted path, we need to perform a replacement
331  if( uncommittedExists )
332  old->second = newPath;
333  }
334  } // end loop over child's children
335  } // end if dirty and child has children
336  } // end loop over children
337 
338  // Insert chained relations
339  for( auto const & it : unregisteredRelations )
340  {
341  auto & derivedMap = baseMap.find( it.first )->second;
342  derivedMap[it.second.first] = it.second.second;
343  reverseMap.insert( {it.second.first, it.first} );
344  }
345 
346  // Mark current parent as modified
347  dirtySet.insert( parent );
348 
349  // Insert all parents of the current parent node that haven't yet been processed
350  auto parentRange = reverseMap.equal_range( parent );
351  for( auto pIter = parentRange.first; pIter != parentRange.second; ++pIter )
352  {
353  const auto pParent = pIter->second;
354  if( !processedParents.count( pParent ) )
355  {
356  parentStack.push( pParent );
357  processedParents.insert( pParent );
358  }
359  }
360  } // end loop over parent stack
361  } // end chainable relations
362  } // end PolymorphicVirtualCaster()
363 
365  void const * downcast( void const * const ptr ) const override
366  {
367  return dynamic_cast<Derived const*>( static_cast<Base const*>( ptr ) );
368  }
369 
371  void * upcast( void * const ptr ) const override
372  {
373  return dynamic_cast<Base*>( static_cast<Derived*>( ptr ) );
374  }
375 
377  std::shared_ptr<void> upcast( std::shared_ptr<void> const & ptr ) const override
378  {
379  return std::dynamic_pointer_cast<Base>( std::static_pointer_cast<Derived>( ptr ) );
380  }
381  };
382 
384 
390  template <class Base, class Derived>
392  {
393  static PolymorphicCaster const * bind( std::true_type /* is_polymorphic<Base> */)
394  {
396  }
397 
398  static PolymorphicCaster const * bind( std::false_type /* is_polymorphic<Base> */ )
399  { return nullptr; }
400 
402 
403  static PolymorphicCaster const * bind()
404  { return bind( typename std::is_polymorphic<Base>::type() ); }
405  };
406  }
407 
408  /* General polymorphism support */
409  namespace detail
410  {
412  template <class T>
413  struct binding_name {};
414 
416 
420  template <class Archive>
422  {
424 
429  typedef std::function<void(void*, void const *, std::type_info const &)> Serializer;
430 
432  struct Serializers
433  {
434  Serializer shared_ptr,
435  unique_ptr;
436  };
437 
439  std::map<std::type_index, Serializers> map;
440  };
441 
443  template<class T> struct EmptyDeleter { void operator()(T *) const {} };
444 
446 
450  template <class Archive>
452  {
454 
459  typedef std::function<void(void*, std::shared_ptr<void> &, std::type_info const &)> SharedSerializer;
461  typedef std::function<void(void*, std::unique_ptr<void, EmptyDeleter<void>> &, std::type_info const &)> UniqueSerializer;
462 
464  struct Serializers
465  {
468  };
469 
471  std::map<std::string, Serializers> map;
472  };
473 
474  // forward decls for archives from cereal.hpp
475  class InputArchiveBase;
476  class OutputArchiveBase;
477 
479 
483  template <class Archive, class T> struct InputBindingCreator
484  {
487  {
488  auto & map = StaticObject<InputBindingMap<Archive>>::getInstance().map;
489  auto lock = StaticObject<InputBindingMap<Archive>>::lock();
490  auto key = std::string(binding_name<T>::name());
491  auto lb = map.lower_bound(key);
492 
493  if (lb != map.end() && lb->first == key)
494  return;
495 
496  typename InputBindingMap<Archive>::Serializers serializers;
497 
498  serializers.shared_ptr =
499  [](void * arptr, std::shared_ptr<void> & dptr, std::type_info const & baseInfo)
500  {
501  Archive & ar = *static_cast<Archive*>(arptr);
502  std::shared_ptr<T> ptr;
503 
504  ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
505 
506  dptr = PolymorphicCasters::template upcast<T>( ptr, baseInfo );
507  };
508 
509  serializers.unique_ptr =
510  [](void * arptr, std::unique_ptr<void, EmptyDeleter<void>> & dptr, std::type_info const & baseInfo)
511  {
512  Archive & ar = *static_cast<Archive*>(arptr);
513  std::unique_ptr<T> ptr;
514 
515  ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
516 
517  dptr.reset( PolymorphicCasters::template upcast<T>( ptr.release(), baseInfo ));
518  };
519 
520  map.insert( lb, { std::move(key), std::move(serializers) } );
521  }
522  };
523 
525 
529  template <class Archive, class T> struct OutputBindingCreator
530  {
532  static void writeMetadata(Archive & ar)
533  {
534  // Register the polymorphic type name with the archive, and get the id
535  char const * name = binding_name<T>::name();
536  std::uint32_t id = ar.registerPolymorphicType(name);
537 
538  // Serialize the id
539  ar( CEREAL_NVP_("polymorphic_id", id) );
540 
541  // If the msb of the id is 1, then the type name is new, and we should serialize it
542  if( id & detail::msb_32bit )
543  {
544  std::string namestring(name);
545  ar( CEREAL_NVP_("polymorphic_name", namestring) );
546  }
547  }
548 
551  {
552  public:
565  PolymorphicSharedPointerWrapper( T const * dptr ) : refCount(), wrappedPtr( refCount, dptr )
566  { }
567 
569  inline std::shared_ptr<T const> const & operator()() const { return wrappedPtr; }
570 
571  private:
572  std::shared_ptr<void> refCount;
573  std::shared_ptr<T const> wrappedPtr;
574  };
575 
577 
584  static inline void savePolymorphicSharedPtr( Archive & ar, T const * dptr, std::true_type /* has_shared_from_this */ )
585  {
586  ::cereal::memory_detail::EnableSharedStateHelper<T> state( const_cast<T *>(dptr) );
587  PolymorphicSharedPointerWrapper psptr( dptr );
588  ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
589  }
590 
592 
599  static inline void savePolymorphicSharedPtr( Archive & ar, T const * dptr, std::false_type /* has_shared_from_this */ )
600  {
601  PolymorphicSharedPointerWrapper psptr( dptr );
602  ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
603  }
604 
607  {
608  auto & map = StaticObject<OutputBindingMap<Archive>>::getInstance().map;
609  auto key = std::type_index(typeid(T));
610  auto lb = map.lower_bound(key);
611 
612  if (lb != map.end() && lb->first == key)
613  return;
614 
615  typename OutputBindingMap<Archive>::Serializers serializers;
616 
617  serializers.shared_ptr =
618  [&](void * arptr, void const * dptr, std::type_info const & baseInfo)
619  {
620  Archive & ar = *static_cast<Archive*>(arptr);
621  writeMetadata(ar);
622 
623  auto ptr = PolymorphicCasters::template downcast<T>( dptr, baseInfo );
624 
625  #ifdef _MSC_VER
626  savePolymorphicSharedPtr( ar, ptr, ::cereal::traits::has_shared_from_this<T>::type() ); // MSVC doesn't like typename here
627  #else // not _MSC_VER
628  savePolymorphicSharedPtr( ar, ptr, typename ::cereal::traits::has_shared_from_this<T>::type() );
629  #endif // _MSC_VER
630  };
631 
632  serializers.unique_ptr =
633  [&](void * arptr, void const * dptr, std::type_info const & baseInfo)
634  {
635  Archive & ar = *static_cast<Archive*>(arptr);
636  writeMetadata(ar);
637 
638  std::unique_ptr<T const, EmptyDeleter<T const>> const ptr( PolymorphicCasters::template downcast<T>( dptr, baseInfo ) );
639 
640  ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
641  };
642 
643  map.insert( { std::move(key), std::move(serializers) } );
644  }
645  };
646 
649  struct adl_tag {};
650 
653  namespace { struct polymorphic_binding_tag {}; }
654 
656  template <class Archive, class T>
658  {
659  static const InputBindingCreator<Archive, T> &
660  load(std::true_type)
661  {
663  }
664 
665  static const OutputBindingCreator<Archive, T> &
666  save(std::true_type)
667  {
669  }
670 
671  inline static void load(std::false_type) {}
672  inline static void save(std::false_type) {}
673  };
674 
676  template <void(*)()>
678 
684  template <class Archive, class T>
686  {
687  #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
688  virtual CEREAL_DLL_EXPORT void instantiate() CEREAL_USED;
691  #else // NOT _MSC_VER
692  static CEREAL_DLL_EXPORT void instantiate() CEREAL_USED;
697  #endif // _MSC_VER
698  };
699 
700  // instantiate implementation
701  template <class Archive, class T>
703  {
704  create_bindings<Archive,T>::save( std::integral_constant<bool,
705  std::is_base_of<detail::OutputArchiveBase, Archive>::value &&
707 
708  create_bindings<Archive,T>::load( std::integral_constant<bool,
709  std::is_base_of<detail::InputArchiveBase, Archive>::value &&
711  }
712 
714 
718  template <class T, class Tag = polymorphic_binding_tag>
720  {
722  void bind(std::false_type) const
723  {
724  instantiate_polymorphic_binding(static_cast<T*>(nullptr), 0, Tag{}, adl_tag{});
725  }
726 
728  void bind(std::true_type) const
729  { }
730 
732 
734  bind_to_archives const & bind() const
735  {
736  static_assert( std::is_polymorphic<T>::value,
737  "Attempting to register non polymorphic type" );
738  bind( std::is_abstract<T>() );
739  return *this;
740  }
741  };
742 
744  template <class T, class Tag = polymorphic_binding_tag>
745  struct init_binding;
746 
748 
759  template <class T, typename BindingTag>
760  void instantiate_polymorphic_binding( T*, int, BindingTag, adl_tag ) {}
761  } // namespace detail
762 } // namespace cereal
763 
764 #endif // CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
#define CEREAL_NVP_(name, value)
Convenience for creating a templated NVP.
Definition: helpers.hpp:199
Creates a binding (map entry) between an input archive type and a polymorphic type.
Definition: polymorphic_impl.hpp:483
static void * upcast(Derived *const dptr, std::type_info const &baseInfo)
Performs an upcast to the registered base type using the given a derived type.
Definition: polymorphic_impl.hpp:189
virtual void * upcast(void *const ptr) const =0
Upcast to proper base type.
Struct containing the serializer functions for all pointer types.
Definition: polymorphic_impl.hpp:432
When specialized, causes the compiler to instantiate its parameter.
Definition: polymorphic_impl.hpp:677
static PolymorphicCaster const * bind()
Performs registration (binding) between Base and Derived.
Definition: polymorphic_impl.hpp:403
std::function< void(void *, std::shared_ptr< void > &, std::type_info const &)> SharedSerializer
Shared ptr serializer function.
Definition: polymorphic_impl.hpp:459
Used to hide the static object used to bind T to registered archives.
Definition: polymorphic_impl.hpp:745
Base type for polymorphic void casting.
Definition: polymorphic_impl.hpp:96
Holds registered mappings between base and derived types for casting.
Definition: polymorphic_impl.hpp:116
Strongly typed derivation of PolymorphicCaster.
Definition: polymorphic_impl.hpp:218
PolymorphicVirtualCaster()
Inserts an entry in the polymorphic casting map for this pairing.
Definition: polymorphic_impl.hpp:224
Serializer unique_ptr
Serializer function for unique pointers.
Definition: polymorphic_impl.hpp:434
Holds a properly typed shared_ptr to the polymorphic type.
Definition: polymorphic_impl.hpp:550
std::shared_ptr< T const > const & operator()() const
Get the wrapped shared_ptr */.
Definition: polymorphic_impl.hpp:569
Registers a polymorphic casting relation between a Base and Derived type.
Definition: polymorphic_impl.hpp:391
static LockGuard lock()
Attempts to lock this static object for the current scope.
Definition: static_object.hpp:109
bind_to_archives const & bind() const
Binds the type T to all registered archives.
Definition: polymorphic_impl.hpp:734
Determine if T or any base class of T has inherited from std::enable_shared_from_this.
Definition: traits.hpp:1194
void bind(std::false_type) const
Binding for non abstract types.
Definition: polymorphic_impl.hpp:722
PolymorphicSharedPointerWrapper(T const *dptr)
Definition: polymorphic_impl.hpp:565
Definition: access.hpp:40
Serializer shared_ptr
Serializer function for shared/weak pointers.
Definition: polymorphic_impl.hpp:434
SharedSerializer shared_ptr
Serializer function for shared/weak pointers.
Definition: polymorphic_impl.hpp:466
Struct containing the serializer functions for all pointer types.
Definition: polymorphic_impl.hpp:464
#define UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(LoadSave)
Error message used for unregistered polymorphic casts.
Definition: polymorphic_impl.hpp:124
std::function< void(void *, void const *, std::type_info const &)> Serializer
A serializer function.
Definition: polymorphic_impl.hpp:429
static void savePolymorphicSharedPtr(Archive &ar, T const *dptr, std::true_type)
Does the actual work of saving a polymorphic shared_ptr.
Definition: polymorphic_impl.hpp:584
OutputBindingCreator()
Initialize the binding.
Definition: polymorphic_impl.hpp:606
std::map< std::string, Serializers > map
A map of serializers for pointers of all registered types.
Definition: polymorphic_impl.hpp:471
static CEREAL_DLL_EXPORT void instantiate() CEREAL_USED
Definition: polymorphic_impl.hpp:702
Definition: traits.hpp:1089
Definition: polymorphic_impl.hpp:649
Creates a binding (map entry) between an output archive type and a polymorphic type.
Definition: polymorphic_impl.hpp:529
static bool exists(std::type_index const &baseIndex, std::type_index const &derivedIndex)
Checks if the mapping object that can perform the upcast or downcast.
Definition: polymorphic_impl.hpp:133
Support for types found in
Causes the static object bindings between an archive type and a serializable type T...
Definition: polymorphic_impl.hpp:657
static void writeMetadata(Archive &ar)
Writes appropriate metadata to the archive for this polymorphic type.
Definition: polymorphic_impl.hpp:532
#define CEREAL_NOEXCEPT
Defines the CEREAL_NOEXCEPT macro to use instead of noexcept.
Definition: macros.hpp:130
void * upcast(void *const ptr) const override
Performs the proper upcast with the templated types.
Definition: polymorphic_impl.hpp:371
An empty noop deleter.
Definition: polymorphic_impl.hpp:443
InputBindingCreator()
Initialize the binding.
Definition: polymorphic_impl.hpp:486
static void savePolymorphicSharedPtr(Archive &ar, T const *dptr, std::false_type)
Does the actual work of saving a polymorphic shared_ptr.
Definition: polymorphic_impl.hpp:599
Internal polymorphism support forward declarations.
std::map< std::type_index, std::map< std::type_index, std::vector< PolymorphicCaster const * > > > map
Maps from base type index to a map from derived type index to caster.
Definition: polymorphic_impl.hpp:119
std::map< std::type_index, Serializers > map
A map of serializers for pointers of all registered types.
Definition: polymorphic_impl.hpp:439
Binds a compile time type with a user defined string.
Definition: polymorphic_impl.hpp:413
Definition: helpers.hpp:230
#define CEREAL_DLL_EXPORT
Prevent link optimization from removing non-referenced static objects.
Definition: static_object.hpp:51
static std::shared_ptr< void > upcast(std::shared_ptr< Derived > const &dptr, std::type_info const &baseInfo)
Upcasts for shared pointers.
Definition: polymorphic_impl.hpp:202
std::function< void(void *, std::unique_ptr< void, EmptyDeleter< void >> &, std::type_info const &)> UniqueSerializer
Unique ptr serializer function.
Definition: polymorphic_impl.hpp:461
static const Derived * downcast(const void *dptr, std::type_info const &baseInfo)
Performs a downcast to the derived type using a registered mapping.
Definition: polymorphic_impl.hpp:175
static std::vector< PolymorphicCaster const * > const & lookup(std::type_index const &baseIndex, std::type_index const &derivedIndex, F &&exceptionFunc)
Gets the mapping object that can perform the upcast or downcast.
Definition: polymorphic_impl.hpp:156
A structure holding a map from type name strings to input serializer functions.
Definition: polymorphic_impl.hpp:451
Begins the binding process of a type to all registered archives.
Definition: polymorphic_impl.hpp:719
Definition: helpers.hpp:242
Definition: traits.hpp:1116
UniqueSerializer unique_ptr
Serializer function for unique pointers.
Definition: polymorphic_impl.hpp:467
A static, pre-execution object.
Definition: static_object.hpp:67
void const * downcast(void const *const ptr) const override
Performs the proper downcast with the templated types.
Definition: polymorphic_impl.hpp:365
A structure holding a map from type_indices to output serializer functions.
Definition: polymorphic_impl.hpp:421
Support for types found in
Internal polymorphism static object support.
virtual void const * downcast(void const *const ptr) const =0
Downcasts to the proper derived type.
void bind(std::true_type) const
Binding for abstract types.
Definition: polymorphic_impl.hpp:728
std::shared_ptr< void > upcast(std::shared_ptr< void > const &ptr) const override
Performs the proper upcast with the templated types (shared_ptr version)
Definition: polymorphic_impl.hpp:377