polymorphic_impl.hpp
Go to the documentation of this file.
/*
Copyright (c) 2014, Randolph Voorhies, Shane Grant
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* This code is heavily inspired by the boost serialization implementation by the following authors
(C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt)
See http://www.boost.org for updates, documentation, and revision history.
(C) Copyright 2006 David Abrahams - http://www.boost.org.
See /boost/serialization/export.hpp, /boost/archive/detail/register_archive.hpp,
and /boost/serialization/void_cast.hpp for their implementation. Additional details
found in other files split across serialization and archive.
*/
#ifndef CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
#define CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
#include "cereal/details/polymorphic_impl_fwd.hpp"
#include "cereal/details/static_object.hpp"
#include "cereal/types/memory.hpp"
#include "cereal/types/string.hpp"
#include <functional>
#include <typeindex>
#include <map>
#include <limits>
#include <set>
#include <stack>
#if defined(__GNUC__)
// GCC / clang don't want the function
#define CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION
#else
#define CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION static void unused() { (void)b; }
#endif
#ifdef CEREAL_HAS_CPP17
#define CEREAL_BIND_TO_ARCHIVES(...) \
namespace cereal { \
namespace detail { \
template<> \
struct init_binding<__VA_ARGS__> { \
static inline bind_to_archives<__VA_ARGS__> const & b= \
::cereal::detail::StaticObject< \
bind_to_archives<__VA_ARGS__> \
>::getInstance().bind(); \
CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION \
}; \
}} /* end namespaces */
#else
#define CEREAL_BIND_TO_ARCHIVES(...) \
namespace cereal { \
namespace detail { \
template<> \
struct init_binding<__VA_ARGS__> { \
static bind_to_archives<__VA_ARGS__> const& b; \
CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION \
}; \
bind_to_archives<__VA_ARGS__> const & init_binding<__VA_ARGS__>::b = \
::cereal::detail::StaticObject< \
bind_to_archives<__VA_ARGS__> \
>::getInstance().bind(); \
}} /* end namespaces */
#endif
namespace cereal
{
/* Polymorphic casting support */
namespace detail
{
struct PolymorphicCaster
{
PolymorphicCaster() = default;
PolymorphicCaster( const PolymorphicCaster & ) = default;
PolymorphicCaster & operator=( const PolymorphicCaster & ) = default;
PolymorphicCaster( PolymorphicCaster && ) CEREAL_NOEXCEPT {}
PolymorphicCaster & operator=( PolymorphicCaster && ) CEREAL_NOEXCEPT { return *this; }
virtual ~PolymorphicCaster() CEREAL_NOEXCEPT = default;
virtual void const * downcast( void const * const ptr ) const = 0;
virtual void * upcast( void * const ptr ) const = 0;
virtual std::shared_ptr<void> upcast( std::shared_ptr<void> const & ptr ) const = 0;
};
struct PolymorphicCasters
{
using DerivedCasterMap = std::unordered_map<std::type_index, std::vector<PolymorphicCaster const *>>;
std::unordered_map<std::type_index, DerivedCasterMap> map;
std::multimap<std::type_index, std::type_index> reverseMap;
#define UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(LoadSave) \
throw cereal::Exception("Trying to " #LoadSave " a registered polymorphic type with an unregistered polymorphic cast.\n" \
"Could not find a path to a base class (" + util::demangle(baseInfo.name()) + ") for type: " + ::cereal::util::demangledName<Derived>() + "\n" \
"Make sure you either serialize the base class at some point via cereal::base_class or cereal::virtual_base_class.\n" \
"Alternatively, manually register the association with CEREAL_REGISTER_POLYMORPHIC_RELATION.");
static std::pair<bool, std::vector<PolymorphicCaster const *> const &>
lookup_if_exists( std::type_index const & baseIndex, std::type_index const & derivedIndex )
{
// First phase of lookup - match base type index
auto const & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
auto baseIter = baseMap.find( baseIndex );
if (baseIter == baseMap.end())
return {false, {}};
// Second phase - find a match from base to derived
auto const & derivedMap = baseIter->second;
auto derivedIter = derivedMap.find( derivedIndex );
if (derivedIter == derivedMap.end())
return {false, {}};
return {true, derivedIter->second};
}
template <class F> inline
static std::vector<PolymorphicCaster const *> const & lookup( std::type_index const & baseIndex, std::type_index const & derivedIndex, F && exceptionFunc )
{
// First phase of lookup - match base type index
auto const & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
auto baseIter = baseMap.find( baseIndex );
if( baseIter == baseMap.end() )
exceptionFunc();
// Second phase - find a match from base to derived
auto const & derivedMap = baseIter->second;
auto derivedIter = derivedMap.find( derivedIndex );
if( derivedIter == derivedMap.end() )
exceptionFunc();
return derivedIter->second;
}
template <class Derived> inline
static const Derived * downcast( const void * dptr, std::type_info const & baseInfo )
{
auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(save) } );
for( auto const * dmap : mapping )
dptr = dmap->downcast( dptr );
return static_cast<Derived const *>( dptr );
}
template <class Derived> inline
static void * upcast( Derived * const dptr, std::type_info const & baseInfo )
{
auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } );
void * uptr = dptr;
for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter )
uptr = (*mIter)->upcast( uptr );
return uptr;
}
template <class Derived> inline
static std::shared_ptr<void> upcast( std::shared_ptr<Derived> const & dptr, std::type_info const & baseInfo )
{
auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } );
std::shared_ptr<void> uptr = dptr;
for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter )
uptr = (*mIter)->upcast( uptr );
return uptr;
}
#undef UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION
};
#ifdef CEREAL_OLDER_GCC
#define CEREAL_EMPLACE_MAP(map, key, value) \
map.insert( std::make_pair(std::move(key), std::move(value)) );
#else // NOT CEREAL_OLDER_GCC
#define CEREAL_EMPLACE_MAP(map, key, value) \
map.emplace( key, value );
#endif // NOT_CEREAL_OLDER_GCC
template <class Base, class Derived>
struct PolymorphicVirtualCaster : PolymorphicCaster
{
PolymorphicVirtualCaster()
{
const auto baseKey = std::type_index(typeid(Base));
const auto derivedKey = std::type_index(typeid(Derived));
// First insert the relation Base->Derived
const auto lock = StaticObject<PolymorphicCasters>::lock();
auto & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
{
auto & derivedMap = baseMap.insert( {baseKey, PolymorphicCasters::DerivedCasterMap{}} ).first->second;
auto & derivedVec = derivedMap.insert( {derivedKey, {}} ).first->second;
derivedVec.push_back( this );
}
// Insert reverse relation Derived->Base
auto & reverseMap = StaticObject<PolymorphicCasters>::getInstance().reverseMap;
CEREAL_EMPLACE_MAP(reverseMap, derivedKey, baseKey);
// Find all chainable unregistered relations
/* The strategy here is to process only the nodes in the class hierarchy graph that have been
affected by the new insertion. The aglorithm iteratively processes a node an ensures that it
is updated with all new shortest length paths. It then rocesses the parents of the active node,
with the knowledge that all children have already been processed.
Note that for the following, we'll use the nomenclature of parent and child to not confuse with
the inserted base derived relationship */
{
// Checks whether there is a path from parent->child and returns a <dist, path> pair
// dist is set to MAX if the path does not exist
auto checkRelation = [](std::type_index const & parentInfo, std::type_index const & childInfo) ->
std::pair<size_t, std::vector<PolymorphicCaster const *> const &>
{
auto result = PolymorphicCasters::lookup_if_exists( parentInfo, childInfo );
if( result.first )
{
auto const & path = result.second;
return {path.size(), path};
}
else
return {(std::numeric_limits<size_t>::max)(), {}};
};
std::stack<std::type_index> parentStack; // Holds the parent nodes to be processed
std::vector<std::type_index> dirtySet; // Marks child nodes that have been changed
std::unordered_set<std::type_index> processedParents; // Marks parent nodes that have been processed
// Checks if a child has been marked dirty
auto isDirty = [&](std::type_index const & c)
{
auto const dirtySetSize = dirtySet.size();
for( size_t i = 0; i < dirtySetSize; ++i )
if( dirtySet[i] == c )
return true;
return false;
};
// Begin processing the base key and mark derived as dirty
parentStack.push( baseKey );
dirtySet.emplace_back( derivedKey );
while( !parentStack.empty() )
{
using Relations = std::unordered_multimap<std::type_index, std::pair<std::type_index, std::vector<PolymorphicCaster const *>>>;
Relations unregisteredRelations; // Defer insertions until after main loop to prevent iterator invalidation
const auto parent = parentStack.top();
parentStack.pop();
// Update paths to all children marked dirty
for( auto const & childPair : baseMap[parent] )
{
const auto child = childPair.first;
if( isDirty( child ) && baseMap.count( child ) )
{
auto parentChildPath = checkRelation( parent, child );
// Search all paths from the child to its own children (finalChild),
// looking for a shorter parth from parent to finalChild
for( auto const & finalChildPair : baseMap[child] )
{
const auto finalChild = finalChildPair.first;
auto parentFinalChildPath = checkRelation( parent, finalChild );
auto childFinalChildPath = checkRelation( child, finalChild );
const size_t newLength = 1u + parentChildPath.first;
if( newLength < parentFinalChildPath.first )
{
std::vector<PolymorphicCaster const *> path = parentChildPath.second;
path.insert( path.end(), childFinalChildPath.second.begin(), childFinalChildPath.second.end() );
// Check to see if we have a previous uncommitted path in unregisteredRelations
// that is shorter. If so, ignore this path
auto hintRange = unregisteredRelations.equal_range( parent );
auto hint = hintRange.first;
for( ; hint != hintRange.second; ++hint )
if( hint->second.first == finalChild )
break;
const bool uncommittedExists = hint != unregisteredRelations.end();
if( uncommittedExists && (hint->second.second.size() <= newLength) )
continue;
auto newPath = std::pair<std::type_index, std::vector<PolymorphicCaster const *>>{finalChild, std::move(path)};
// Insert the new path if it doesn't exist, otherwise this will just lookup where to do the
// replacement
#ifdef CEREAL_OLDER_GCC
auto old = unregisteredRelations.insert( hint, std::make_pair(parent, newPath) );
#else // NOT CEREAL_OLDER_GCC
auto old = unregisteredRelations.emplace_hint( hint, parent, newPath );
#endif // NOT CEREAL_OLDER_GCC
// If there was an uncommitted path, we need to perform a replacement
if( uncommittedExists )
old->second = newPath;
}
} // end loop over child's children
} // end if dirty and child has children
} // end loop over children
// Insert chained relations
for( auto const & it : unregisteredRelations )
{
auto & derivedMap = baseMap.find( it.first )->second;
derivedMap[it.second.first] = it.second.second;
CEREAL_EMPLACE_MAP(reverseMap, it.second.first, it.first );
}
// Mark current parent as modified
dirtySet.emplace_back( parent );
// Insert all parents of the current parent node that haven't yet been processed
auto parentRange = reverseMap.equal_range( parent );
for( auto pIter = parentRange.first; pIter != parentRange.second; ++pIter )
{
const auto pParent = pIter->second;
if( !processedParents.count( pParent ) )
{
parentStack.push( pParent );
processedParents.insert( pParent );
}
}
} // end loop over parent stack
} // end chainable relations
} // end PolymorphicVirtualCaster()
#undef CEREAL_EMPLACE_MAP
void const * downcast( void const * const ptr ) const override
{
return dynamic_cast<Derived const*>( static_cast<Base const*>( ptr ) );
}
void * upcast( void * const ptr ) const override
{
return dynamic_cast<Base*>( static_cast<Derived*>( ptr ) );
}
std::shared_ptr<void> upcast( std::shared_ptr<void> const & ptr ) const override
{
return std::dynamic_pointer_cast<Base>( std::static_pointer_cast<Derived>( ptr ) );
}
};
template <class Base, class Derived>
struct RegisterPolymorphicCaster
{
static PolymorphicCaster const * bind( std::true_type /* is_polymorphic<Base> */)
{
return &StaticObject<PolymorphicVirtualCaster<Base, Derived>>::getInstance();
}
static PolymorphicCaster const * bind( std::false_type /* is_polymorphic<Base> */ )
{ return nullptr; }
static PolymorphicCaster const * bind()
{ return bind( typename std::is_polymorphic<Base>::type() ); }
};
}
/* General polymorphism support */
namespace detail
{
template <class T>
struct binding_name {};
template <class Archive>
struct OutputBindingMap
{
typedef std::function<void(void*, void const *, std::type_info const &)> Serializer;
struct Serializers
{
Serializer shared_ptr,
unique_ptr;
};
std::map<std::type_index, Serializers> map;
};
template<class T> struct EmptyDeleter { void operator()(T *) const {} };
template <class Archive>
struct InputBindingMap
{
typedef std::function<void(void*, std::shared_ptr<void> &, std::type_info const &)> SharedSerializer;
typedef std::function<void(void*, std::unique_ptr<void, EmptyDeleter<void>> &, std::type_info const &)> UniqueSerializer;
struct Serializers
{
SharedSerializer shared_ptr;
UniqueSerializer unique_ptr;
};
std::map<std::string, Serializers> map;
};
// forward decls for archives from cereal.hpp
class InputArchiveBase;
class OutputArchiveBase;
template <class Archive, class T> struct InputBindingCreator
{
InputBindingCreator()
{
auto & map = StaticObject<InputBindingMap<Archive>>::getInstance().map;
auto lock = StaticObject<InputBindingMap<Archive>>::lock();
auto key = std::string(binding_name<T>::name());
auto lb = map.lower_bound(key);
if (lb != map.end() && lb->first == key)
return;
typename InputBindingMap<Archive>::Serializers serializers;
serializers.shared_ptr =
[](void * arptr, std::shared_ptr<void> & dptr, std::type_info const & baseInfo)
{
Archive & ar = *static_cast<Archive*>(arptr);
std::shared_ptr<T> ptr;
ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
dptr = PolymorphicCasters::template upcast<T>( ptr, baseInfo );
};
serializers.unique_ptr =
[](void * arptr, std::unique_ptr<void, EmptyDeleter<void>> & dptr, std::type_info const & baseInfo)
{
Archive & ar = *static_cast<Archive*>(arptr);
std::unique_ptr<T> ptr;
ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
dptr.reset( PolymorphicCasters::template upcast<T>( ptr.release(), baseInfo ));
};
map.insert( lb, { std::move(key), std::move(serializers) } );
}
};
template <class Archive, class T> struct OutputBindingCreator
{
static void writeMetadata(Archive & ar)
{
// Register the polymorphic type name with the archive, and get the id
char const * name = binding_name<T>::name();
std::uint32_t id = ar.registerPolymorphicType(name);
// Serialize the id
ar( CEREAL_NVP_("polymorphic_id", id) );
// If the msb of the id is 1, then the type name is new, and we should serialize it
if( id & detail::msb_32bit )
{
std::string namestring(name);
ar( CEREAL_NVP_("polymorphic_name", namestring) );
}
}
class PolymorphicSharedPointerWrapper
{
public:
PolymorphicSharedPointerWrapper( T const * dptr ) : refCount(), wrappedPtr( refCount, dptr )
{ }
inline std::shared_ptr<T const> const & operator()() const { return wrappedPtr; }
private:
std::shared_ptr<void> refCount;
std::shared_ptr<T const> wrappedPtr;
};
static inline void savePolymorphicSharedPtr( Archive & ar, T const * dptr, std::true_type /* has_shared_from_this */ )
{
::cereal::memory_detail::EnableSharedStateHelper<T> state( const_cast<T *>(dptr) );
PolymorphicSharedPointerWrapper psptr( dptr );
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
}
static inline void savePolymorphicSharedPtr( Archive & ar, T const * dptr, std::false_type /* has_shared_from_this */ )
{
PolymorphicSharedPointerWrapper psptr( dptr );
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
}
OutputBindingCreator()
{
auto & map = StaticObject<OutputBindingMap<Archive>>::getInstance().map;
auto key = std::type_index(typeid(T));
auto lb = map.lower_bound(key);
if (lb != map.end() && lb->first == key)
return;
typename OutputBindingMap<Archive>::Serializers serializers;
serializers.shared_ptr =
[&](void * arptr, void const * dptr, std::type_info const & baseInfo)
{
Archive & ar = *static_cast<Archive*>(arptr);
writeMetadata(ar);
auto ptr = PolymorphicCasters::template downcast<T>( dptr, baseInfo );
#if defined(_MSC_VER) && _MSC_VER < 1916 && !defined(__clang__)
savePolymorphicSharedPtr( ar, ptr, ::cereal::traits::has_shared_from_this<T>::type() ); // MSVC doesn't like typename here
#else // not _MSC_VER
savePolymorphicSharedPtr( ar, ptr, typename ::cereal::traits::has_shared_from_this<T>::type() );
#endif // _MSC_VER
};
serializers.unique_ptr =
[&](void * arptr, void const * dptr, std::type_info const & baseInfo)
{
Archive & ar = *static_cast<Archive*>(arptr);
writeMetadata(ar);
std::unique_ptr<T const, EmptyDeleter<T const>> const ptr( PolymorphicCasters::template downcast<T>( dptr, baseInfo ) );
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
};
map.insert( { std::move(key), std::move(serializers) } );
}
};
struct adl_tag {};
#ifdef CEREAL_HAS_CPP17
struct polymorphic_binding_tag {};
#else
namespace { struct polymorphic_binding_tag {}; }
#endif
template <class Archive, class T>
struct create_bindings
{
static const InputBindingCreator<Archive, T> &
load(std::true_type)
{
return cereal::detail::StaticObject<InputBindingCreator<Archive, T>>::getInstance();
}
static const OutputBindingCreator<Archive, T> &
save(std::true_type)
{
return cereal::detail::StaticObject<OutputBindingCreator<Archive, T>>::getInstance();
}
inline static void load(std::false_type) {}
inline static void save(std::false_type) {}
};
template <void(*)()>
struct instantiate_function {};
template <class Archive, class T>
struct polymorphic_serialization_support
{
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
virtual CEREAL_DLL_EXPORT void instantiate() CEREAL_USED;
#else // NOT _MSC_VER
static CEREAL_DLL_EXPORT void instantiate() CEREAL_USED;
typedef instantiate_function<instantiate> unused;
#endif // _MSC_VER
};
// instantiate implementation
template <class Archive, class T>
CEREAL_DLL_EXPORT void polymorphic_serialization_support<Archive,T>::instantiate()
{
create_bindings<Archive,T>::save( std::integral_constant<bool,
std::is_base_of<detail::OutputArchiveBase, Archive>::value &&
traits::is_output_serializable<T, Archive>::value>{} );
create_bindings<Archive,T>::load( std::integral_constant<bool,
std::is_base_of<detail::InputArchiveBase, Archive>::value &&
traits::is_input_serializable<T, Archive>::value>{} );
}
template <class T, class Tag = polymorphic_binding_tag>
struct bind_to_archives
{
void bind(std::false_type) const
{
instantiate_polymorphic_binding(static_cast<T*>(nullptr), 0, Tag{}, adl_tag{});
}
void bind(std::true_type) const
{ }
bind_to_archives const & bind() const
{
static_assert( std::is_polymorphic<T>::value,
"Attempting to register non polymorphic type" );
bind( std::is_abstract<T>() );
return *this;
}
};
template <class T, class Tag = polymorphic_binding_tag>
struct init_binding;
template <class T, typename BindingTag>
void instantiate_polymorphic_binding( T*, int, BindingTag, adl_tag ) {}
} // namespace detail
} // namespace cereal
#endif // CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
cereal::detail::instantiate_polymorphic_binding
void instantiate_polymorphic_binding(T *, int, BindingTag, adl_tag)
Base case overload for instantiation.
Definition: polymorphic_impl.hpp:821
cereal::detail::OutputBindingCreator::PolymorphicSharedPointerWrapper::operator()
const std::shared_ptr< T const > & operator()() const
Get the wrapped shared_ptr *‍/.
Definition: polymorphic_impl.hpp:616
CEREAL_NVP_
#define CEREAL_NVP_(name, value)
Convenience for creating a templated NVP.
Definition: helpers.hpp:201
cereal::detail::InputBindingMap::SharedSerializer
std::function< void(void *, std::shared_ptr< void > &, std::type_info const &)> SharedSerializer
Shared ptr serializer function.
Definition: polymorphic_impl.hpp:506
cereal::detail::InputBindingMap::Serializers::shared_ptr
SharedSerializer shared_ptr
Serializer function for shared/weak pointers.
Definition: polymorphic_impl.hpp:513
cereal::detail::OutputArchiveBase
Definition: helpers.hpp:269
cereal::detail::OutputBindingMap::Serializers::shared_ptr
Serializer shared_ptr
Serializer function for shared/weak pointers.
Definition: polymorphic_impl.hpp:481
cereal::detail::PolymorphicVirtualCaster::upcast
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
cereal::detail::PolymorphicCaster::downcast
virtual const void * downcast(void const *const ptr) const =0
Downcasts to the proper derived type.
cereal::detail::init_binding
Used to hide the static object used to bind T to registered archives.
Definition: polymorphic_impl.hpp:806
cereal::detail::InputBindingCreator
Creates a binding (map entry) between an input archive type and a polymorphic type.
Definition: polymorphic_impl.hpp:530
cereal::detail::PolymorphicCasters::lookup_if_exists
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
memory.hpp
Support for types found in <memory>
cereal::detail::OutputBindingMap::Serializers::unique_ptr
Serializer unique_ptr
Serializer function for unique pointers.
Definition: polymorphic_impl.hpp:482
cereal::detail::polymorphic_serialization_support
Definition: helpers.hpp:294
cereal::detail::PolymorphicCasters
Holds registered mappings between base and derived types for casting.
Definition: polymorphic_impl.hpp:139
cereal::detail::instantiate_function
When specialized, causes the compiler to instantiate its parameter.
Definition: polymorphic_impl.hpp:738
cereal::detail::OutputBindingMap::map
std::map< std::type_index, Serializers > map
A map of serializers for pointers of all registered types.
Definition: polymorphic_impl.hpp:486
string.hpp
Support for types found in <string>
cereal::detail::PolymorphicCaster
Base type for polymorphic void casting.
Definition: polymorphic_impl.hpp:119
CEREAL_DLL_EXPORT
#define CEREAL_DLL_EXPORT
Prevent link optimization from removing non-referenced static objects.
Definition: static_object.hpp:51
cereal::detail::StaticObject
A static, pre-execution object.
Definition: static_object.hpp:67
cereal::detail::PolymorphicCasters::lookup
static const std::vector< PolymorphicCaster 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
cereal::detail::PolymorphicVirtualCaster
Strongly typed derivation of PolymorphicCaster.
Definition: polymorphic_impl.hpp:253
cereal::detail::StaticObject::lock
static LockGuard lock()
Attempts to lock this static object for the current scope.
Definition: static_object.hpp:110
cereal::detail::InputBindingCreator::InputBindingCreator
InputBindingCreator()
Initialize the binding.
Definition: polymorphic_impl.hpp:533
cereal::detail::OutputBindingCreator::PolymorphicSharedPointerWrapper
Holds a properly typed shared_ptr to the polymorphic type.
Definition: polymorphic_impl.hpp:597
UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION
#define UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(LoadSave)
Error message used for unregistered polymorphic casts.
Definition: polymorphic_impl.hpp:149
cereal::detail::PolymorphicCasters::upcast
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
cereal::detail::adl_tag
Definition: polymorphic_impl.hpp:696
cereal::detail::OutputBindingMap::Serializers
Struct containing the serializer functions for all pointer types.
Definition: polymorphic_impl.hpp:479
cereal::traits::is_output_serializable
Definition: traits.hpp:1111
cereal::detail::InputBindingMap::Serializers::unique_ptr
UniqueSerializer unique_ptr
Serializer function for unique pointers.
Definition: polymorphic_impl.hpp:514
cereal::detail::OutputBindingMap
A structure holding a map from type_indices to output serializer functions.
Definition: polymorphic_impl.hpp:468
cereal::detail::PolymorphicCasters::downcast
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
cereal::detail::binding_name
Binds a compile time type with a user defined string.
Definition: polymorphic_impl.hpp:460
cereal::memory_detail::EnableSharedStateHelper
Definition: memory.hpp:132
cereal::detail::PolymorphicCaster::upcast
virtual void * upcast(void *const ptr) const =0
Upcast to proper base type.
cereal::detail::PolymorphicCasters::DerivedCasterMap
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
cereal::detail::PolymorphicCasters::upcast
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
cereal::detail::OutputBindingCreator::PolymorphicSharedPointerWrapper::PolymorphicSharedPointerWrapper
PolymorphicSharedPointerWrapper(T const *dptr)
Definition: polymorphic_impl.hpp:612
cereal::detail::InputBindingMap::Serializers
Struct containing the serializer functions for all pointer types.
Definition: polymorphic_impl.hpp:511
cereal::detail::bind_to_archives::bind
void bind(std::true_type) const
Binding for abstract types.
Definition: polymorphic_impl.hpp:789
cereal::detail::OutputBindingCreator::writeMetadata
static void writeMetadata(Archive &ar)
Writes appropriate metadata to the archive for this polymorphic type.
Definition: polymorphic_impl.hpp:579
cereal::detail::OutputBindingCreator::OutputBindingCreator
OutputBindingCreator()
Initialize the binding.
Definition: polymorphic_impl.hpp:653
cereal::detail::OutputBindingCreator::savePolymorphicSharedPtr
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
cereal::traits::has_shared_from_this
Determine if T or any base class of T has inherited from std::enable_shared_from_this.
Definition: traits.hpp:1216
CEREAL_NOEXCEPT
#define CEREAL_NOEXCEPT
Defines the CEREAL_NOEXCEPT macro to use instead of noexcept.
Definition: macros.hpp:130
cereal::detail::EmptyDeleter
An empty noop deleter.
Definition: polymorphic_impl.hpp:490
static_object.hpp
Internal polymorphism static object support.
cereal::detail::OutputBindingCreator::savePolymorphicSharedPtr
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
cereal::detail::bind_to_archives::bind
const bind_to_archives & bind() const
Binds the type T to all registered archives.
Definition: polymorphic_impl.hpp:795
cereal::detail::create_bindings
Causes the static object bindings between an archive type and a serializable type T.
Definition: polymorphic_impl.hpp:718
polymorphic_impl_fwd.hpp
Internal polymorphism support forward declarations.
cereal::detail::RegisterPolymorphicCaster
Registers a polymorphic casting relation between a Base and Derived type.
Definition: polymorphic_impl.hpp:438
cereal::detail::OutputBindingCreator
Creates a binding (map entry) between an output archive type and a polymorphic type.
Definition: polymorphic_impl.hpp:576
cereal::detail::InputBindingMap
A structure holding a map from type name strings to input serializer functions.
Definition: polymorphic_impl.hpp:498
cereal::detail::InputBindingMap::map
std::map< std::string, Serializers > map
A map of serializers for pointers of all registered types.
Definition: polymorphic_impl.hpp:518
cereal::detail::PolymorphicCasters::map
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
cereal::detail::RegisterPolymorphicCaster::bind
static const PolymorphicCaster * bind()
Performs registration (binding) between Base and Derived.
Definition: polymorphic_impl.hpp:450
cereal::detail::InputArchiveBase
Definition: helpers.hpp:281
cereal::detail::PolymorphicVirtualCaster::upcast
void * upcast(void *const ptr) const override
Performs the proper upcast with the templated types.
Definition: polymorphic_impl.hpp:418
cereal::detail::bind_to_archives::bind
void bind(std::false_type) const
Binding for non abstract types.
Definition: polymorphic_impl.hpp:783
cereal::detail::PolymorphicVirtualCaster::downcast
const void * downcast(void const *const ptr) const override
Performs the proper downcast with the templated types.
Definition: polymorphic_impl.hpp:412
cereal::traits::is_input_serializable
Definition: traits.hpp:1138
cereal::detail::bind_to_archives
Begins the binding process of a type to all registered archives.
Definition: polymorphic_impl.hpp:780
cereal::detail::PolymorphicVirtualCaster::PolymorphicVirtualCaster
PolymorphicVirtualCaster()
Inserts an entry in the polymorphic casting map for this pairing.
Definition: polymorphic_impl.hpp:259
cereal::detail::InputBindingMap::UniqueSerializer
std::function< void(void *, std::unique_ptr< void, EmptyDeleter< void >> &, std::type_info const &)> UniqueSerializer
Unique ptr serializer function.
Definition: polymorphic_impl.hpp:508
cereal::detail::OutputBindingMap::Serializer
std::function< void(void *, void const *, std::type_info const &)> Serializer
A serializer function.
Definition: polymorphic_impl.hpp:476