NDDEM
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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 #if defined(__GNUC__)
61  // GCC / clang don't want the function
62  #define CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION
63 #else
64  #define CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION static void unused() { (void)b; }
65 #endif
66 
68 
72 #ifdef CEREAL_HAS_CPP17
73 #define CEREAL_BIND_TO_ARCHIVES(...) \
74  namespace cereal { \
75  namespace detail { \
76  template<> \
77  struct init_binding<__VA_ARGS__> { \
78  static inline bind_to_archives<__VA_ARGS__> const & b= \
79  ::cereal::detail::StaticObject< \
80  bind_to_archives<__VA_ARGS__> \
81  >::getInstance().bind(); \
82  CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION \
83  }; \
84  }} /* end namespaces */
85 #else
86 #define CEREAL_BIND_TO_ARCHIVES(...) \
87  namespace cereal { \
88  namespace detail { \
89  template<> \
90  struct init_binding<__VA_ARGS__> { \
91  static bind_to_archives<__VA_ARGS__> const& b; \
92  CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION \
93  }; \
94  bind_to_archives<__VA_ARGS__> const & init_binding<__VA_ARGS__>::b = \
95  ::cereal::detail::StaticObject< \
96  bind_to_archives<__VA_ARGS__> \
97  >::getInstance().bind(); \
98  }} /* end namespaces */
99 #endif
100 
101 namespace cereal
102 {
103  /* Polymorphic casting support */
104  namespace detail
105  {
107 
120  {
121  PolymorphicCaster() = default;
122  PolymorphicCaster( const PolymorphicCaster & ) = default;
126  virtual ~PolymorphicCaster() CEREAL_NOEXCEPT = default;
127 
129  virtual void const * downcast( void const * const ptr ) const = 0;
131  virtual void * upcast( void * const ptr ) const = 0;
133  virtual std::shared_ptr<void> upcast( std::shared_ptr<void> const & ptr ) const = 0;
134  };
135 
137 
140  {
142  using DerivedCasterMap = std::unordered_map<std::type_index, std::vector<PolymorphicCaster const *>>;
144  std::unordered_map<std::type_index, DerivedCasterMap> map;
145 
146  std::multimap<std::type_index, std::type_index> reverseMap;
147 
149  #define UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(LoadSave) \
150  throw cereal::Exception("Trying to " #LoadSave " a registered polymorphic type with an unregistered polymorphic cast.\n" \
151  "Could not find a path to a base class (" + util::demangle(baseInfo.name()) + ") for type: " + ::cereal::util::demangledName<Derived>() + "\n" \
152  "Make sure you either serialize the base class at some point via cereal::base_class or cereal::virtual_base_class.\n" \
153  "Alternatively, manually register the association with CEREAL_REGISTER_POLYMORPHIC_RELATION.");
154 
156 
159  static std::pair<bool, std::vector<PolymorphicCaster const *> const &>
160  lookup_if_exists( std::type_index const & baseIndex, std::type_index const & derivedIndex )
161  {
162  // First phase of lookup - match base type index
163  auto const & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
164  auto baseIter = baseMap.find( baseIndex );
165  if (baseIter == baseMap.end())
166  return {false, {}};
167 
168  // Second phase - find a match from base to derived
169  auto const & derivedMap = baseIter->second;
170  auto derivedIter = derivedMap.find( derivedIndex );
171  if (derivedIter == derivedMap.end())
172  return {false, {}};
173 
174  return {true, derivedIter->second};
175  }
176 
178 
182  template <class F> inline
183  static std::vector<PolymorphicCaster const *> const & lookup( std::type_index const & baseIndex, std::type_index const & derivedIndex, F && exceptionFunc )
184  {
185  // First phase of lookup - match base type index
186  auto const & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
187  auto baseIter = baseMap.find( baseIndex );
188  if( baseIter == baseMap.end() )
189  exceptionFunc();
190 
191  // Second phase - find a match from base to derived
192  auto const & derivedMap = baseIter->second;
193  auto derivedIter = derivedMap.find( derivedIndex );
194  if( derivedIter == derivedMap.end() )
195  exceptionFunc();
196 
197  return derivedIter->second;
198  }
199 
201  template <class Derived> inline
202  static const Derived * downcast( const void * dptr, std::type_info const & baseInfo )
203  {
204  auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(save) } );
205 
206  for( auto const * dmap : mapping )
207  dptr = dmap->downcast( dptr );
208 
209  return static_cast<Derived const *>( dptr );
210  }
211 
213 
215  template <class Derived> inline
216  static void * upcast( Derived * const dptr, std::type_info const & baseInfo )
217  {
218  auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } );
219 
220  void * uptr = dptr;
221  for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter )
222  uptr = (*mIter)->upcast( uptr );
223 
224  return uptr;
225  }
226 
228  template <class Derived> inline
229  static std::shared_ptr<void> upcast( std::shared_ptr<Derived> const & dptr, std::type_info const & baseInfo )
230  {
231  auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } );
232 
233  std::shared_ptr<void> uptr = dptr;
234  for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter )
235  uptr = (*mIter)->upcast( uptr );
236 
237  return uptr;
238  }
239 
240  #undef UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION
241  };
242 
243  #ifdef CEREAL_OLDER_GCC
244  #define CEREAL_EMPLACE_MAP(map, key, value) \
245  map.insert( std::make_pair(std::move(key), std::move(value)) );
246  #else // NOT CEREAL_OLDER_GCC
247  #define CEREAL_EMPLACE_MAP(map, key, value) \
248  map.emplace( key, value );
249  #endif // NOT_CEREAL_OLDER_GCC
250 
252  template <class Base, class Derived>
254  {
256 
260  {
261  const auto baseKey = std::type_index(typeid(Base));
262  const auto derivedKey = std::type_index(typeid(Derived));
263 
264  // First insert the relation Base->Derived
265  const auto lock = StaticObject<PolymorphicCasters>::lock();
266  auto & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
267 
268  {
269  auto & derivedMap = baseMap.insert( {baseKey, PolymorphicCasters::DerivedCasterMap{}} ).first->second;
270  auto & derivedVec = derivedMap.insert( {derivedKey, {}} ).first->second;
271  derivedVec.push_back( this );
272  }
273 
274  // Insert reverse relation Derived->Base
275  auto & reverseMap = StaticObject<PolymorphicCasters>::getInstance().reverseMap;
276  CEREAL_EMPLACE_MAP(reverseMap, derivedKey, baseKey);
277 
278  // Find all chainable unregistered relations
279  /* The strategy here is to process only the nodes in the class hierarchy graph that have been
280  affected by the new insertion. The algorithm iteratively processes a node an ensures that it
281  is updated with all new shortest length paths. It then processes the parents of the active node,
282  with the knowledge that all children have already been processed.
283 
284  Note that for the following, we'll use the nomenclature of parent and child to not confuse with
285  the inserted base derived relationship */
286  {
287  // Checks whether there is a path from parent->child and returns a <dist, path> pair
288  // dist is set to MAX if the path does not exist
289  auto checkRelation = [](std::type_index const & parentInfo, std::type_index const & childInfo) ->
290  std::pair<size_t, std::vector<PolymorphicCaster const *> const &>
291  {
292  auto result = PolymorphicCasters::lookup_if_exists( parentInfo, childInfo );
293  if( result.first )
294  {
295  auto const & path = result.second;
296  return {path.size(), path};
297  }
298  else
299  return {(std::numeric_limits<size_t>::max)(), {}};
300  };
301 
302  std::stack<std::type_index> parentStack; // Holds the parent nodes to be processed
303  std::vector<std::type_index> dirtySet; // Marks child nodes that have been changed
304  std::unordered_set<std::type_index> processedParents; // Marks parent nodes that have been processed
305 
306  // Checks if a child has been marked dirty
307  auto isDirty = [&](std::type_index const & c)
308  {
309  auto const dirtySetSize = dirtySet.size();
310  for( size_t i = 0; i < dirtySetSize; ++i )
311  if( dirtySet[i] == c )
312  return true;
313 
314  return false;
315  };
316 
317  // Begin processing the base key and mark derived as dirty
318  parentStack.push( baseKey );
319  dirtySet.emplace_back( derivedKey );
320 
321  while( !parentStack.empty() )
322  {
323  using Relations = std::unordered_multimap<std::type_index, std::pair<std::type_index, std::vector<PolymorphicCaster const *>>>;
324  Relations unregisteredRelations; // Defer insertions until after main loop to prevent iterator invalidation
325 
326  const auto parent = parentStack.top();
327  parentStack.pop();
328 
329  // Update paths to all children marked dirty
330  for( auto const & childPair : baseMap[parent] )
331  {
332  const auto child = childPair.first;
333  if( isDirty( child ) && baseMap.count( child ) )
334  {
335  auto parentChildPath = checkRelation( parent, child );
336 
337  // Search all paths from the child to its own children (finalChild),
338  // looking for a shorter path from parent to finalChild
339  for( auto const & finalChildPair : baseMap[child] )
340  {
341  const auto finalChild = finalChildPair.first;
342 
343  auto parentFinalChildPath = checkRelation( parent, finalChild );
344  auto childFinalChildPath = checkRelation( child, finalChild );
345 
346  const size_t newLength = 1u + parentChildPath.first;
347 
348  if( newLength < parentFinalChildPath.first )
349  {
350  std::vector<PolymorphicCaster const *> path = parentChildPath.second;
351  path.insert( path.end(), childFinalChildPath.second.begin(), childFinalChildPath.second.end() );
352 
353  // Check to see if we have a previous uncommitted path in unregisteredRelations
354  // that is shorter. If so, ignore this path
355  auto hintRange = unregisteredRelations.equal_range( parent );
356  auto hint = hintRange.first;
357  for( ; hint != hintRange.second; ++hint )
358  if( hint->second.first == finalChild )
359  break;
360 
361  const bool uncommittedExists = hint != unregisteredRelations.end();
362  if( uncommittedExists && (hint->second.second.size() <= newLength) )
363  continue;
364 
365  auto newPath = std::pair<std::type_index, std::vector<PolymorphicCaster const *>>{finalChild, std::move(path)};
366 
367  // Insert the new path if it doesn't exist, otherwise this will just lookup where to do the
368  // replacement
369  #ifdef CEREAL_OLDER_GCC
370  auto old = unregisteredRelations.insert( hint, std::make_pair(parent, newPath) );
371  #else // NOT CEREAL_OLDER_GCC
372  auto old = unregisteredRelations.emplace_hint( hint, parent, newPath );
373  #endif // NOT CEREAL_OLDER_GCC
374 
375  // If there was an uncommitted path, we need to perform a replacement
376  if( uncommittedExists )
377  old->second = newPath;
378  }
379  } // end loop over child's children
380  } // end if dirty and child has children
381  } // end loop over children
382 
383  // Insert chained relations
384  for( auto const & it : unregisteredRelations )
385  {
386  auto & derivedMap = baseMap.find( it.first )->second;
387  derivedMap[it.second.first] = it.second.second;
388  CEREAL_EMPLACE_MAP(reverseMap, it.second.first, it.first );
389  }
390 
391  // Mark current parent as modified
392  dirtySet.emplace_back( parent );
393 
394  // Insert all parents of the current parent node that haven't yet been processed
395  auto parentRange = reverseMap.equal_range( parent );
396  for( auto pIter = parentRange.first; pIter != parentRange.second; ++pIter )
397  {
398  const auto pParent = pIter->second;
399  if( !processedParents.count( pParent ) )
400  {
401  parentStack.push( pParent );
402  processedParents.insert( pParent );
403  }
404  }
405  } // end loop over parent stack
406  } // end chainable relations
407  } // end PolymorphicVirtualCaster()
408 
409  #undef CEREAL_EMPLACE_MAP
410 
412  void const * downcast( void const * const ptr ) const override
413  {
414  return dynamic_cast<Derived const*>( static_cast<Base const*>( ptr ) );
415  }
416 
418  void * upcast( void * const ptr ) const override
419  {
420  return dynamic_cast<Base*>( static_cast<Derived*>( ptr ) );
421  }
422 
424  std::shared_ptr<void> upcast( std::shared_ptr<void> const & ptr ) const override
425  {
426  return std::dynamic_pointer_cast<Base>( std::static_pointer_cast<Derived>( ptr ) );
427  }
428  };
429 
431 
437  template <class Base, class Derived>
439  {
440  static PolymorphicCaster const * bind( std::true_type /* is_polymorphic<Base> */)
441  {
443  }
444 
445  static PolymorphicCaster const * bind( std::false_type /* is_polymorphic<Base> */ )
446  { return nullptr; }
447 
449 
450  static PolymorphicCaster const * bind()
451  { return bind( typename std::is_polymorphic<Base>::type() ); }
452  };
453  }
454 
455  /* General polymorphism support */
456  namespace detail
457  {
459  template <class T>
460  struct binding_name {};
461 
463 
467  template <class Archive>
469  {
471 
476  typedef std::function<void(void*, void const *, std::type_info const &)> Serializer;
477 
479  struct Serializers
480  {
483  };
484 
486  std::map<std::type_index, Serializers> map;
487  };
488 
490  template<class T> struct EmptyDeleter { void operator()(T *) const {} };
491 
493 
497  template <class Archive>
499  {
501 
506  typedef std::function<void(void*, std::shared_ptr<void> &, std::type_info const &)> SharedSerializer;
508  typedef std::function<void(void*, std::unique_ptr<void, EmptyDeleter<void>> &, std::type_info const &)> UniqueSerializer;
509 
511  struct Serializers
512  {
515  };
516 
518  std::map<std::string, Serializers> map;
519  };
520 
521  // forward decls for archives from cereal.hpp
522  class InputArchiveBase;
523  class OutputArchiveBase;
524 
526 
530  template <class Archive, class T> struct InputBindingCreator
531  {
534  {
535  auto & map = StaticObject<InputBindingMap<Archive>>::getInstance().map;
536  auto lock = StaticObject<InputBindingMap<Archive>>::lock();
537  auto key = std::string(binding_name<T>::name());
538  auto lb = map.lower_bound(key);
539 
540  if (lb != map.end() && lb->first == key)
541  return;
542 
543  typename InputBindingMap<Archive>::Serializers serializers;
544 
545  serializers.shared_ptr =
546  [](void * arptr, std::shared_ptr<void> & dptr, std::type_info const & baseInfo)
547  {
548  Archive & ar = *static_cast<Archive*>(arptr);
549  std::shared_ptr<T> ptr;
550 
551  ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
552 
553  dptr = PolymorphicCasters::template upcast<T>( ptr, baseInfo );
554  };
555 
556  serializers.unique_ptr =
557  [](void * arptr, std::unique_ptr<void, EmptyDeleter<void>> & dptr, std::type_info const & baseInfo)
558  {
559  Archive & ar = *static_cast<Archive*>(arptr);
560  std::unique_ptr<T> ptr;
561 
562  ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
563 
564  dptr.reset( PolymorphicCasters::template upcast<T>( ptr.release(), baseInfo ));
565  };
566 
567  map.insert( lb, { std::move(key), std::move(serializers) } );
568  }
569  };
570 
572 
576  template <class Archive, class T> struct OutputBindingCreator
577  {
579  static void writeMetadata(Archive & ar)
580  {
581  // Register the polymorphic type name with the archive, and get the id
582  char const * name = binding_name<T>::name();
583  std::uint32_t id = ar.registerPolymorphicType(name);
584 
585  // Serialize the id
586  ar( CEREAL_NVP_("polymorphic_id", id) );
587 
588  // If the msb of the id is 1, then the type name is new, and we should serialize it
589  if( id & detail::msb_32bit )
590  {
591  std::string namestring(name);
592  ar( CEREAL_NVP_("polymorphic_name", namestring) );
593  }
594  }
595 
598  {
599  public:
613  { }
614 
616  inline std::shared_ptr<T const> const & operator()() const { return wrappedPtr; }
617 
618  private:
619  std::shared_ptr<void> refCount;
620  std::shared_ptr<T const> wrappedPtr;
621  };
622 
624 
631  static inline void savePolymorphicSharedPtr( Archive & ar, T const * dptr, std::true_type /* has_shared_from_this */ )
632  {
633  ::cereal::memory_detail::EnableSharedStateHelper<T> state( const_cast<T *>(dptr) );
634  PolymorphicSharedPointerWrapper psptr( dptr );
635  ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
636  }
637 
639 
646  static inline void savePolymorphicSharedPtr( Archive & ar, T const * dptr, std::false_type /* has_shared_from_this */ )
647  {
648  PolymorphicSharedPointerWrapper psptr( dptr );
649  ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
650  }
651 
654  {
655  auto & map = StaticObject<OutputBindingMap<Archive>>::getInstance().map;
656  auto key = std::type_index(typeid(T));
657  auto lb = map.lower_bound(key);
658 
659  if (lb != map.end() && lb->first == key)
660  return;
661 
662  typename OutputBindingMap<Archive>::Serializers serializers;
663 
664  serializers.shared_ptr =
665  [&](void * arptr, void const * dptr, std::type_info const & baseInfo)
666  {
667  Archive & ar = *static_cast<Archive*>(arptr);
668  writeMetadata(ar);
669 
670  auto ptr = PolymorphicCasters::template downcast<T>( dptr, baseInfo );
671 
672  #if defined(_MSC_VER) && _MSC_VER < 1916 && !defined(__clang__)
673  savePolymorphicSharedPtr( ar, ptr, ::cereal::traits::has_shared_from_this<T>::type() ); // MSVC doesn't like typename here
674  #else // not _MSC_VER
676  #endif // _MSC_VER
677  };
678 
679  serializers.unique_ptr =
680  [&](void * arptr, void const * dptr, std::type_info const & baseInfo)
681  {
682  Archive & ar = *static_cast<Archive*>(arptr);
683  writeMetadata(ar);
684 
685  std::unique_ptr<T const, EmptyDeleter<T const>> const ptr( PolymorphicCasters::template downcast<T>( dptr, baseInfo ) );
686 
687  ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
688  };
689 
690  map.insert( { std::move(key), std::move(serializers) } );
691  }
692  };
693 
696  struct adl_tag {};
697 
709 #ifdef CEREAL_HAS_CPP17
710  struct polymorphic_binding_tag {};
711 #else
712  namespace { struct polymorphic_binding_tag {}; }
713 #endif
714 
715 
717  template <class Archive, class T>
719  {
720  static const InputBindingCreator<Archive, T> &
721  load(std::true_type)
722  {
724  }
725 
726  static const OutputBindingCreator<Archive, T> &
727  save(std::true_type)
728  {
730  }
731 
732  inline static void load(std::false_type) {}
733  inline static void save(std::false_type) {}
734  };
735 
737  template <void(*)()>
739 
745  template <class Archive, class T>
747  {
748  #if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
752  #else // NOT _MSC_VER
755  static CEREAL_DLL_EXPORT void instantiate() CEREAL_USED;
758  #endif // _MSC_VER
759  };
760 
761  // instantiate implementation
762  template <class Archive, class T>
764  {
765  create_bindings<Archive,T>::save( std::integral_constant<bool,
768 
769  create_bindings<Archive,T>::load( std::integral_constant<bool,
772  }
773 
775 
779  template <class T, class Tag = polymorphic_binding_tag>
781  {
783  void bind(std::false_type) const
784  {
785  instantiate_polymorphic_binding(static_cast<T*>(nullptr), 0, Tag{}, adl_tag{});
786  }
787 
789  void bind(std::true_type) const
790  { }
791 
793 
795  bind_to_archives const & bind() const
796  {
797  static_assert( std::is_polymorphic<T>::value,
798  "Attempting to register non polymorphic type" );
799  bind( std::is_abstract<T>() );
800  return *this;
801  }
802  };
803 
805  template <class T, class Tag = polymorphic_binding_tag>
806  struct init_binding;
807 
809 
820  template <class T, typename BindingTag>
821  void instantiate_polymorphic_binding( T*, int, BindingTag, adl_tag ) {}
822  } // namespace detail
823 } // namespace cereal
824 
825 #endif // CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
Definition: helpers.hpp:282
Definition: helpers.hpp:270
Holds a properly typed shared_ptr to the polymorphic type.
Definition: polymorphic_impl.hpp:598
PolymorphicSharedPointerWrapper(T const *dptr)
Definition: polymorphic_impl.hpp:612
std::shared_ptr< T const > wrappedPtr
The wrapped pointer.
Definition: polymorphic_impl.hpp:620
std::shared_ptr< T const > const & operator()() const
Get the wrapped shared_ptr *‍/.
Definition: polymorphic_impl.hpp:616
std::shared_ptr< void > refCount
The ownership pointer.
Definition: polymorphic_impl.hpp:619
A static, pre-execution object.
Definition: static_object.hpp:68
static T & getInstance()
Definition: static_object.hpp:82
static LockGuard lock()
Attempts to lock this static object for the current scope.
Definition: static_object.hpp:110
#define CEREAL_NVP_(name, value)
Convenience for creating a templated NVP.
Definition: helpers.hpp:201
#define CEREAL_NOEXCEPT
Defines the CEREAL_NOEXCEPT macro to use instead of noexcept.
Definition: macros.hpp:130
Support for types found in <memory>
type
The type the bitset is encoded with.
Definition: bitset.hpp:44
void instantiate_polymorphic_binding(T *, int, BindingTag, adl_tag)
Base case overload for instantiation.
Definition: polymorphic_impl.hpp:821
static const uint32_t msb_32bit
Definition: helpers.hpp:298
PtrWrapper< T > make_ptr_wrapper(T &&t)
Make a PtrWrapper.
Definition: memory.hpp:57
void save(Archive &ar, SetT const &set)
Definition: set.hpp:42
void load(Archive &ar, SetT &set)
Definition: set.hpp:52
in certain simple scenarios. They should probably not be used if maximizing performance is the main o...
Definition: access.hpp:42
detail namespace with internal helper functions
Definition: json.hpp:260
Definition: json.hpp:5678
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1282
#define CEREAL_EMPLACE_MAP(map, key, value)
Definition: polymorphic_impl.hpp:247
#define UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(LoadSave)
Error message used for unregistered polymorphic casts.
Definition: polymorphic_impl.hpp:149
Internal polymorphism support forward declarations.
Internal polymorphism static object support.
#define CEREAL_USED
Definition: static_object.hpp:52
#define CEREAL_DLL_EXPORT
Prevent link optimization from removing non-referenced static objects.
Definition: static_object.hpp:51
unsigned int uint32_t
Definition: stdint.h:126
Support for types found in <string>
An empty noop deleter.
Definition: polymorphic_impl.hpp:490
void operator()(T *) const
Definition: polymorphic_impl.hpp:490
Creates a binding (map entry) between an input archive type and a polymorphic type.
Definition: polymorphic_impl.hpp:531
InputBindingCreator()
Initialize the binding.
Definition: polymorphic_impl.hpp:533
Struct containing the serializer functions for all pointer types.
Definition: polymorphic_impl.hpp:512
UniqueSerializer unique_ptr
Serializer function for unique pointers.
Definition: polymorphic_impl.hpp:514
SharedSerializer shared_ptr
Serializer function for shared/weak pointers.
Definition: polymorphic_impl.hpp:513
A structure holding a map from type name strings to input serializer functions.
Definition: polymorphic_impl.hpp:499
std::function< void(void *, std::unique_ptr< void, EmptyDeleter< void >> &, std::type_info const &)> UniqueSerializer
Unique ptr serializer function.
Definition: polymorphic_impl.hpp:508
std::function< void(void *, std::shared_ptr< void > &, std::type_info const &)> SharedSerializer
Shared ptr serializer function.
Definition: polymorphic_impl.hpp:506
std::map< std::string, Serializers > map
A map of serializers for pointers of all registered types.
Definition: polymorphic_impl.hpp:518
Creates a binding (map entry) between an output archive type and a polymorphic type.
Definition: polymorphic_impl.hpp:577
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:631
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:646
static void writeMetadata(Archive &ar)
Writes appropriate metadata to the archive for this polymorphic type.
Definition: polymorphic_impl.hpp:579
OutputBindingCreator()
Initialize the binding.
Definition: polymorphic_impl.hpp:653
Struct containing the serializer functions for all pointer types.
Definition: polymorphic_impl.hpp:480
Serializer shared_ptr
Serializer function for shared/weak pointers.
Definition: polymorphic_impl.hpp:481
Serializer unique_ptr
Serializer function for unique pointers.
Definition: polymorphic_impl.hpp:482
A structure holding a map from type_indices to output serializer functions.
Definition: polymorphic_impl.hpp:469
std::function< void(void *, void const *, std::type_info const &)> Serializer
A serializer function.
Definition: polymorphic_impl.hpp:476
std::map< std::type_index, Serializers > map
A map of serializers for pointers of all registered types.
Definition: polymorphic_impl.hpp:486
Base type for polymorphic void casting.
Definition: polymorphic_impl.hpp:120
PolymorphicCaster(PolymorphicCaster &&) CEREAL_NOEXCEPT
Definition: polymorphic_impl.hpp:124
virtual ~PolymorphicCaster() CEREAL_NOEXCEPT=default
PolymorphicCaster & operator=(const PolymorphicCaster &)=default
virtual void * upcast(void *const ptr) const =0
Upcast to proper base type.
PolymorphicCaster(const PolymorphicCaster &)=default
PolymorphicCaster & operator=(PolymorphicCaster &&) CEREAL_NOEXCEPT
Definition: polymorphic_impl.hpp:125
virtual void const * downcast(void const *const ptr) const =0
Downcasts to the proper derived type.
Holds registered mappings between base and derived types for casting.
Definition: polymorphic_impl.hpp:140
std::multimap< std::type_index, std::type_index > reverseMap
Definition: polymorphic_impl.hpp:146
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:183
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:216
std::unordered_map< std::type_index, std::vector< PolymorphicCaster const * > > DerivedCasterMap
Maps from a derived type index to a set of chainable casters.
Definition: polymorphic_impl.hpp:142
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:229
static std::pair< bool, std::vector< PolymorphicCaster const * > const & > lookup_if_exists(std::type_index const &baseIndex, std::type_index const &derivedIndex)
Checks if the mapping object that can perform the upcast or downcast exists, and returns it if so.
Definition: polymorphic_impl.hpp:160
std::unordered_map< std::type_index, DerivedCasterMap > map
Maps from base type index to a map from derived type index to caster.
Definition: polymorphic_impl.hpp:144
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:202
Strongly typed derivation of PolymorphicCaster.
Definition: polymorphic_impl.hpp:254
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:424
PolymorphicVirtualCaster()
Inserts an entry in the polymorphic casting map for this pairing.
Definition: polymorphic_impl.hpp:259
void * upcast(void *const ptr) const override
Performs the proper upcast with the templated types.
Definition: polymorphic_impl.hpp:418
void const * downcast(void const *const ptr) const override
Performs the proper downcast with the templated types.
Definition: polymorphic_impl.hpp:412
Registers a polymorphic casting relation between a Base and Derived type.
Definition: polymorphic_impl.hpp:439
static PolymorphicCaster const * bind(std::true_type)
Definition: polymorphic_impl.hpp:440
static PolymorphicCaster const * bind(std::false_type)
Definition: polymorphic_impl.hpp:445
static PolymorphicCaster const * bind()
Performs registration (binding) between Base and Derived.
Definition: polymorphic_impl.hpp:450
Definition: polymorphic_impl.hpp:696
Begins the binding process of a type to all registered archives.
Definition: polymorphic_impl.hpp:781
void bind(std::false_type) const
Binding for non abstract types.
Definition: polymorphic_impl.hpp:783
void bind(std::true_type) const
Binding for abstract types.
Definition: polymorphic_impl.hpp:789
bind_to_archives const & bind() const
Binds the type T to all registered archives.
Definition: polymorphic_impl.hpp:795
Binds a compile time type with a user defined string.
Definition: polymorphic_impl.hpp:460
Causes the static object bindings between an archive type and a serializable type T.
Definition: polymorphic_impl.hpp:719
static const OutputBindingCreator< Archive, T > & save(std::true_type)
Definition: polymorphic_impl.hpp:727
static void load(std::false_type)
Definition: polymorphic_impl.hpp:732
static const InputBindingCreator< Archive, T > & load(std::true_type)
Definition: polymorphic_impl.hpp:721
static void save(std::false_type)
Definition: polymorphic_impl.hpp:733
Used to hide the static object used to bind T to registered archives.
Definition: polymorphic_impl.hpp:806
When specialized, causes the compiler to instantiate its parameter.
Definition: polymorphic_impl.hpp:738
Definition: polymorphic_impl.hpp:747
instantiate_function< instantiate > unused
This typedef causes the compiler to instantiate this static function.
Definition: polymorphic_impl.hpp:757
static CEREAL_DLL_EXPORT void instantiate() CEREAL_USED
Definition: polymorphic_impl.hpp:763
Determine if T or any base class of T has inherited from std::enable_shared_from_this.
Definition: traits.hpp:1217
Definition: traits.hpp:1139
Definition: traits.hpp:1112
#define const
Definition: zconf.h:233