Loading...
Searching...
No Matches
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::InputArchiveBase
Definition helpers.hpp:282
cereal::detail::OutputArchiveBase
Definition helpers.hpp:270
cereal::detail::OutputBindingCreator::PolymorphicSharedPointerWrapper
Holds a properly typed shared_ptr to the polymorphic type.
Definition polymorphic_impl.hpp:598
cereal::detail::OutputBindingCreator::PolymorphicSharedPointerWrapper::PolymorphicSharedPointerWrapper
PolymorphicSharedPointerWrapper(T const *dptr)
Definition polymorphic_impl.hpp:612
cereal::detail::OutputBindingCreator::PolymorphicSharedPointerWrapper::operator()
std::shared_ptr< T const > const & operator()() const
Get the wrapped shared_ptr *‍/.
Definition polymorphic_impl.hpp:616
cereal::detail::StaticObject
A static, pre-execution object.
Definition static_object.hpp:68
cereal::detail::StaticObject::lock
static LockGuard lock()
Attempts to lock this static object for the current scope.
Definition static_object.hpp:110
cereal::memory_detail::EnableSharedStateHelper
Definition memory.hpp:133
CEREAL_NVP_
#define CEREAL_NVP_(name, value)
Convenience for creating a templated NVP.
Definition helpers.hpp:201
CEREAL_NOEXCEPT
#define CEREAL_NOEXCEPT
Defines the CEREAL_NOEXCEPT macro to use instead of noexcept.
Definition macros.hpp:130
memory.hpp
Support for types found in <memory>
cereal::detail::instantiate_polymorphic_binding
void instantiate_polymorphic_binding(T *, int, BindingTag, adl_tag)
Base case overload for instantiation.
Definition polymorphic_impl.hpp:821
UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION
#define UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(LoadSave)
Error message used for unregistered polymorphic casts.
Definition polymorphic_impl.hpp:149
polymorphic_impl_fwd.hpp
Internal polymorphism support forward declarations.
static_object.hpp
Internal polymorphism static object support.
CEREAL_DLL_EXPORT
#define CEREAL_DLL_EXPORT
Prevent link optimization from removing non-referenced static objects.
Definition static_object.hpp:51
string.hpp
Support for types found in <string>
cereal::detail::EmptyDeleter
An empty noop deleter.
Definition polymorphic_impl.hpp:490
cereal::detail::InputBindingCreator
Creates a binding (map entry) between an input archive type and a polymorphic type.
Definition polymorphic_impl.hpp:531
cereal::detail::InputBindingCreator::InputBindingCreator
InputBindingCreator()
Initialize the binding.
Definition polymorphic_impl.hpp:533
cereal::detail::InputBindingMap::Serializers
Struct containing the serializer functions for all pointer types.
Definition polymorphic_impl.hpp:512
cereal::detail::InputBindingMap::Serializers::unique_ptr
UniqueSerializer unique_ptr
Serializer function for unique pointers.
Definition polymorphic_impl.hpp:514
cereal::detail::InputBindingMap::Serializers::shared_ptr
SharedSerializer shared_ptr
Serializer function for shared/weak pointers.
Definition polymorphic_impl.hpp:513
cereal::detail::InputBindingMap
A structure holding a map from type name strings to input serializer functions.
Definition polymorphic_impl.hpp:499
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::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::map
std::map< std::string, Serializers > map
A map of serializers for pointers of all registered types.
Definition polymorphic_impl.hpp:518
cereal::detail::OutputBindingCreator
Creates a binding (map entry) between an output archive type and a polymorphic type.
Definition polymorphic_impl.hpp:577
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::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::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::OutputBindingMap::Serializers
Struct containing the serializer functions for all pointer types.
Definition polymorphic_impl.hpp:480
cereal::detail::OutputBindingMap::Serializers::shared_ptr
Serializer shared_ptr
Serializer function for shared/weak pointers.
Definition polymorphic_impl.hpp:481
cereal::detail::OutputBindingMap::Serializers::unique_ptr
Serializer unique_ptr
Serializer function for unique pointers.
Definition polymorphic_impl.hpp:482
cereal::detail::OutputBindingMap
A structure holding a map from type_indices to output serializer functions.
Definition polymorphic_impl.hpp:469
cereal::detail::OutputBindingMap::Serializer
std::function< void(void *, void const *, std::type_info const &)> Serializer
A serializer function.
Definition polymorphic_impl.hpp:476
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
cereal::detail::PolymorphicCaster
Base type for polymorphic void casting.
Definition polymorphic_impl.hpp:120
cereal::detail::PolymorphicCaster::upcast
virtual std::shared_ptr< void > upcast(std::shared_ptr< void > const &ptr) const =0
Upcast to proper base type, shared_ptr version.
cereal::detail::PolymorphicCaster::upcast
virtual void * upcast(void *const ptr) const =0
Upcast to proper base type.
cereal::detail::PolymorphicCaster::downcast
virtual void const * downcast(void const *const ptr) const =0
Downcasts to the proper derived type.
cereal::detail::PolymorphicCasters
Holds registered mappings between base and derived types for casting.
Definition polymorphic_impl.hpp:140
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
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::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::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::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::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::PolymorphicCasters::lookup
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
cereal::detail::PolymorphicVirtualCaster
Strongly typed derivation of PolymorphicCaster.
Definition polymorphic_impl.hpp:254
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::PolymorphicVirtualCaster::PolymorphicVirtualCaster
PolymorphicVirtualCaster()
Inserts an entry in the polymorphic casting map for this pairing.
Definition polymorphic_impl.hpp:259
cereal::detail::PolymorphicVirtualCaster::downcast
void const * downcast(void const *const ptr) const override
Performs the proper downcast with the templated types.
Definition polymorphic_impl.hpp:412
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::RegisterPolymorphicCaster
Registers a polymorphic casting relation between a Base and Derived type.
Definition polymorphic_impl.hpp:439
cereal::detail::RegisterPolymorphicCaster::bind
static PolymorphicCaster const * bind()
Performs registration (binding) between Base and Derived.
Definition polymorphic_impl.hpp:450
cereal::detail::adl_tag
Definition polymorphic_impl.hpp:696
cereal::detail::bind_to_archives
Begins the binding process of a type to all registered archives.
Definition polymorphic_impl.hpp:781
cereal::detail::bind_to_archives::bind
bind_to_archives const & bind() const
Binds the type T to all registered archives.
Definition polymorphic_impl.hpp:795
cereal::detail::bind_to_archives::bind
void bind(std::false_type) const
Binding for non abstract types.
Definition polymorphic_impl.hpp:783
cereal::detail::bind_to_archives::bind
void bind(std::true_type) const
Binding for abstract types.
Definition polymorphic_impl.hpp:789
cereal::detail::binding_name
Binds a compile time type with a user defined string.
Definition polymorphic_impl.hpp:460
cereal::detail::create_bindings
Causes the static object bindings between an archive type and a serializable type T.
Definition polymorphic_impl.hpp:719
cereal::detail::init_binding
Used to hide the static object used to bind T to registered archives.
Definition polymorphic_impl.hpp:806
cereal::detail::instantiate_function
When specialized, causes the compiler to instantiate its parameter.
Definition polymorphic_impl.hpp:738
cereal::detail::polymorphic_serialization_support
Definition polymorphic_impl.hpp:747
cereal::detail::polymorphic_serialization_support::unused
instantiate_function< instantiate > unused
This typedef causes the compiler to instantiate this static function.
Definition polymorphic_impl.hpp:757
cereal::detail::polymorphic_serialization_support::instantiate
static CEREAL_DLL_EXPORT void instantiate() CEREAL_USED
Definition polymorphic_impl.hpp:763
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:1217
cereal::traits::is_input_serializable
Definition traits.hpp:1139
cereal::traits::is_output_serializable
Definition traits.hpp:1112