mirror of
https://github.com/USCiLab/cereal.git
synced 2025-10-18 01:45:52 +02:00
Loading polymorphig shared_ptrs works
This commit is contained in:
@@ -167,11 +167,11 @@ namespace cereal
|
|||||||
} } // end namespaces
|
} } // end namespaces
|
||||||
|
|
||||||
//! The base output archive class
|
//! The base output archive class
|
||||||
template<class ArchiveType, uint32_t Flags = 0>
|
template<class ArchiveType, std::uint32_t Flags = 0>
|
||||||
class OutputArchive : public detail::OutputArchiveBase
|
class OutputArchive : public detail::OutputArchiveBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OutputArchive(ArchiveType * const self) : self(self), itsCurrentPointerId(1)
|
OutputArchive(ArchiveType * const self) : self(self), itsCurrentPointerId(1), itsCurrentPolymorphicTypeId(1)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
//! Serializes all passed in data
|
//! Serializes all passed in data
|
||||||
@@ -183,7 +183,7 @@ namespace cereal
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Registers a pointer with the archive
|
//! Registers a pointer with the archive
|
||||||
uint32_t registerSharedPointer( void const * addr )
|
std::uint32_t registerSharedPointer( void const * addr )
|
||||||
{
|
{
|
||||||
// Handle null pointers by just returning 0
|
// Handle null pointers by just returning 0
|
||||||
if(addr == 0) return 0;
|
if(addr == 0) return 0;
|
||||||
@@ -199,6 +199,20 @@ namespace cereal
|
|||||||
return id->second;
|
return id->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Registers a polymorphic type name with the archive
|
||||||
|
std::uint32_t registerPolymorphicType( char const * name )
|
||||||
|
{
|
||||||
|
auto id = itsPolymorphicTypeMap.find( name );
|
||||||
|
if( id == itsPolymorphicTypeMap.end() )
|
||||||
|
{
|
||||||
|
auto polyId = itsCurrentPolymorphicTypeId++;
|
||||||
|
itsPolymorphicTypeMap.insert( {name, polyId} );
|
||||||
|
return polyId | detail::msb_32bit; // mask MSB to be 1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return id->second;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class T> inline
|
template <class T> inline
|
||||||
void process( T && head )
|
void process( T && head )
|
||||||
@@ -307,15 +321,21 @@ namespace cereal
|
|||||||
std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
|
std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
|
||||||
|
|
||||||
//! Maps from addresses to pointer ids
|
//! Maps from addresses to pointer ids
|
||||||
std::unordered_map<void const *, std::size_t> itsSharedPointerMap;
|
std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap;
|
||||||
|
|
||||||
//! The id to be given to the next pointer
|
//! The id to be given to the next pointer
|
||||||
std::size_t itsCurrentPointerId;
|
std::uint32_t itsCurrentPointerId;
|
||||||
|
|
||||||
|
//! Maps from polymorphic type name strings to ids
|
||||||
|
std::unordered_map<char const *, std::uint32_t> itsPolymorphicTypeMap;
|
||||||
|
|
||||||
|
//! The id to be given to the next polymorphic type name
|
||||||
|
std::uint32_t itsCurrentPolymorphicTypeId;
|
||||||
}; // class OutputArchive
|
}; // class OutputArchive
|
||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
//! The base input archive class
|
//! The base input archive class
|
||||||
template<class ArchiveType, uint32_t Flags = 0>
|
template<class ArchiveType, std::uint32_t Flags = 0>
|
||||||
class InputArchive : public detail::InputArchiveBase
|
class InputArchive : public detail::InputArchiveBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -329,7 +349,7 @@ namespace cereal
|
|||||||
return *self;
|
return *self;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<void> getSharedPointer(uint32_t const id)
|
std::shared_ptr<void> getSharedPointer(std::uint32_t const id)
|
||||||
{
|
{
|
||||||
if(id == 0) return std::shared_ptr<void>(nullptr);
|
if(id == 0) return std::shared_ptr<void>(nullptr);
|
||||||
|
|
||||||
@@ -341,12 +361,27 @@ namespace cereal
|
|||||||
return ptr->second;
|
return ptr->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerSharedPointer(uint32_t const id, std::shared_ptr<void> ptr)
|
void registerSharedPointer(std::uint32_t const id, std::shared_ptr<void> ptr)
|
||||||
{
|
{
|
||||||
uint32_t const stripped_id = id & ~detail::msb_32bit;
|
std::uint32_t const stripped_id = id & ~detail::msb_32bit;
|
||||||
itsSharedPointerMap.insert( {stripped_id, ptr} );
|
itsSharedPointerMap.insert( {stripped_id, ptr} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string getPolymorphicName(std::uint32_t const id)
|
||||||
|
{
|
||||||
|
auto name = itsPolymorphicTypeMap.find( id );
|
||||||
|
if(name == itsPolymorphicTypeMap.end())
|
||||||
|
{
|
||||||
|
throw Exception("Error while trying to deserialize a polymorphic pointer. Could not find type id " + std::to_string(id));
|
||||||
|
}
|
||||||
|
return name->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerPolymorphicName(std::uint32_t const id, std::string const & name)
|
||||||
|
{
|
||||||
|
std::uint32_t const stripped_id = id & ~detail::msb_32bit;
|
||||||
|
itsPolymorphicTypeMap.insert( {stripped_id, name} );
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class T> inline
|
template <class T> inline
|
||||||
@@ -455,8 +490,12 @@ namespace cereal
|
|||||||
//! A set of all base classes that have been serialized
|
//! A set of all base classes that have been serialized
|
||||||
std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
|
std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
|
||||||
|
|
||||||
//! Maps from addresses to pointer ids
|
//! Maps from pointer ids to addresses
|
||||||
std::unordered_map<std::size_t, std::shared_ptr<void>> itsSharedPointerMap;
|
std::unordered_map<std::uint32_t, std::shared_ptr<void>> itsSharedPointerMap;
|
||||||
|
|
||||||
|
//! Maps from name ids to names
|
||||||
|
std::unordered_map<std::uint32_t, std::string> itsPolymorphicTypeMap;
|
||||||
|
|
||||||
}; // class InputArchive
|
}; // class InputArchive
|
||||||
} // namespace cereal
|
} // namespace cereal
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
#include <cereal/details/static_object.hpp>
|
#include <cereal/details/static_object.hpp>
|
||||||
#include <cereal/types/memory.hpp>
|
#include <cereal/types/memory.hpp>
|
||||||
|
#include <cereal/types/string.hpp>
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -72,6 +73,7 @@ namespace cereal
|
|||||||
template <class T>
|
template <class T>
|
||||||
struct binding_name {};
|
struct binding_name {};
|
||||||
|
|
||||||
|
//! A structure holding a map from type_indices to output serializer functions
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
struct OutputBindingMap
|
struct OutputBindingMap
|
||||||
{
|
{
|
||||||
@@ -89,19 +91,61 @@ namespace cereal
|
|||||||
std::map<std::type_index, Serializers> map;
|
std::map<std::type_index, Serializers> map;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! A structure holding a map from type name strings to input serializer functions
|
||||||
|
template <class Archive>
|
||||||
|
struct InputBindingMap
|
||||||
|
{
|
||||||
|
//! A serializer function
|
||||||
|
typedef std::function<void(void*, std::shared_ptr<void> & )> SharedSerializer;
|
||||||
|
typedef std::function<void(void*, std::unique_ptr<void> & )> UniqueSerializer;
|
||||||
|
|
||||||
|
//! Struct containing the serializer functions for all pointer types
|
||||||
|
struct Serializers
|
||||||
|
{
|
||||||
|
SharedSerializer shared_ptr; //!< Serializer function for shared/weak pointers
|
||||||
|
UniqueSerializer unique_ptr; //!< Serializer function for unique pointers
|
||||||
|
};
|
||||||
|
|
||||||
|
//! A map of serializers for pointers of all registered types
|
||||||
|
std::map<std::string, Serializers> map;
|
||||||
|
};
|
||||||
|
|
||||||
//! An empty noop deleter
|
//! An empty noop deleter
|
||||||
template<class T> struct EmptyDeleter { void operator()(T *) const {} };
|
template<class T> struct EmptyDeleter { void operator()(T *) const {} };
|
||||||
|
|
||||||
struct InputArchiveBase;
|
struct InputArchiveBase;
|
||||||
struct OutputArchiveBase;
|
struct OutputArchiveBase;
|
||||||
|
|
||||||
template <class Archive, class T> struct InputBinding
|
template <class Archive, class T> struct InputBindingCreator
|
||||||
{
|
{
|
||||||
|
InputBindingCreator()
|
||||||
|
{
|
||||||
|
typename InputBindingMap<Archive>::Serializers serializers;
|
||||||
|
|
||||||
|
serializers.shared_ptr =
|
||||||
|
[](void * arptr, std::shared_ptr<void> & dptr)
|
||||||
|
{
|
||||||
|
Archive & ar = *static_cast<Archive*>(arptr);
|
||||||
|
std::shared_ptr<T> ptr;
|
||||||
|
|
||||||
|
ar( make_ptr_wrapper(ptr) );
|
||||||
|
|
||||||
|
dptr = ptr;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
serializers.unique_ptr =
|
||||||
|
[](void * arptr, std::unique_ptr<void> & dptr)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
StaticObject<InputBindingMap<Archive>>::getInstance().map.insert( { std::string(binding_name<T>::name()), serializers } );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Archive, class T> struct OutputBinding
|
template <class Archive, class T> struct OutputBindingCreator
|
||||||
{
|
{
|
||||||
OutputBinding( )
|
OutputBindingCreator()
|
||||||
{
|
{
|
||||||
typename OutputBindingMap<Archive>::Serializers serializers;
|
typename OutputBindingMap<Archive>::Serializers serializers;
|
||||||
|
|
||||||
@@ -111,6 +155,20 @@ namespace cereal
|
|||||||
Archive & ar = *static_cast<Archive*>(arptr);
|
Archive & ar = *static_cast<Archive*>(arptr);
|
||||||
std::shared_ptr<T const> const ptr(static_cast<T const *>(dptr), EmptyDeleter<T const>());
|
std::shared_ptr<T const> const ptr(static_cast<T const *>(dptr), EmptyDeleter<T const>());
|
||||||
|
|
||||||
|
// 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( 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(namestring);
|
||||||
|
}
|
||||||
|
|
||||||
ar( detail::make_ptr_wrapper(ptr) );
|
ar( detail::make_ptr_wrapper(ptr) );
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -135,16 +193,16 @@ namespace cereal
|
|||||||
template <class Archive, class T>
|
template <class Archive, class T>
|
||||||
struct create_bindings
|
struct create_bindings
|
||||||
{
|
{
|
||||||
static const InputBinding<Archive, T> &
|
static const InputBindingCreator<Archive, T> &
|
||||||
load(std::true_type)
|
load(std::true_type)
|
||||||
{
|
{
|
||||||
return cereal::detail::StaticObject<InputBinding<Archive, T>>::getInstance();
|
return cereal::detail::StaticObject<InputBindingCreator<Archive, T>>::getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const OutputBinding<Archive, T> &
|
static const OutputBindingCreator<Archive, T> &
|
||||||
save(std::true_type)
|
save(std::true_type)
|
||||||
{
|
{
|
||||||
return cereal::detail::StaticObject<OutputBinding<Archive, T>>::getInstance();
|
return cereal::detail::StaticObject<OutputBindingCreator<Archive, T>>::getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void load(std::false_type) {}
|
inline static void load(std::false_type) {}
|
||||||
|
|||||||
@@ -27,31 +27,6 @@
|
|||||||
#ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
#ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||||
#define CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
#define CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <typeinfo>
|
|
||||||
#include <cxxabi.h>
|
|
||||||
|
|
||||||
namespace cereal
|
|
||||||
{
|
|
||||||
inline std::string demangle(std::string mangledName)
|
|
||||||
{
|
|
||||||
int status = 0;
|
|
||||||
char *demangledName = NULL;
|
|
||||||
std::size_t len;
|
|
||||||
|
|
||||||
demangledName = abi::__cxa_demangle(mangledName.c_str(), 0, &len, &status);
|
|
||||||
|
|
||||||
std::string retName(demangledName);
|
|
||||||
free(demangledName);
|
|
||||||
|
|
||||||
return retName;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T> inline
|
|
||||||
std::string demangledName()
|
|
||||||
{ return demangle(typeid(T).name()); }
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace cereal
|
namespace cereal
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
@@ -74,7 +49,6 @@ namespace cereal
|
|||||||
static T & create()
|
static T & create()
|
||||||
{
|
{
|
||||||
static T t;
|
static T t;
|
||||||
std::cout << demangledName<T>() << std::endl;
|
|
||||||
instantiate(instance);
|
instantiate(instance);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|||||||
58
include/cereal/details/util.hpp
Normal file
58
include/cereal/details/util.hpp
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2013, 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 cereal 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 <COPYRIGHT HOLDER> 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.
|
||||||
|
*/
|
||||||
|
#ifndef CEREAL_DETAILS_UTIL_HPP_
|
||||||
|
#define CEREAL_DETAILS_UTIL_HPP_
|
||||||
|
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <cxxabi.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace cereal
|
||||||
|
{
|
||||||
|
namespace util
|
||||||
|
{
|
||||||
|
inline std::string demangle(std::string mangledName)
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
char *demangledName = NULL;
|
||||||
|
std::size_t len;
|
||||||
|
|
||||||
|
demangledName = abi::__cxa_demangle(mangledName.c_str(), 0, &len, &status);
|
||||||
|
|
||||||
|
std::string retName(demangledName);
|
||||||
|
free(demangledName);
|
||||||
|
|
||||||
|
return retName;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> inline
|
||||||
|
std::string demangledName()
|
||||||
|
{ return demangle(typeid(T).name()); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CEREAL_DETAILS_UTIL_HPP_
|
||||||
@@ -30,14 +30,19 @@
|
|||||||
#include <cereal/cereal.hpp>
|
#include <cereal/cereal.hpp>
|
||||||
#include <cereal/types/memory.hpp>
|
#include <cereal/types/memory.hpp>
|
||||||
#include <cereal/details/polymorphic_impl.hpp>
|
#include <cereal/details/polymorphic_impl.hpp>
|
||||||
|
#include <cereal/details/util.hpp>
|
||||||
|
|
||||||
#define CEREAL_REGISTER_TYPE(T) \
|
#include <iostream>
|
||||||
namespace cereal { \
|
|
||||||
namespace detail { \
|
#define CEREAL_REGISTER_TYPE(T) \
|
||||||
template <> \
|
namespace cereal { \
|
||||||
struct binding_name<T> \
|
namespace detail { \
|
||||||
{ static const char * name = #T; }; \
|
template <> \
|
||||||
} } /* end namespaces */ \
|
struct binding_name<T> \
|
||||||
|
{ \
|
||||||
|
static constexpr char const * name() { return #T; }; \
|
||||||
|
}; \
|
||||||
|
} } /* end namespaces */ \
|
||||||
CEREAL_BIND_TO_ARCHIVES(T);
|
CEREAL_BIND_TO_ARCHIVES(T);
|
||||||
|
|
||||||
#define CEREAL_REGISTER_TYPE_WITH_NAME(T, Name)\
|
#define CEREAL_REGISTER_TYPE_WITH_NAME(T, Name)\
|
||||||
@@ -45,7 +50,7 @@
|
|||||||
namespace detail { \
|
namespace detail { \
|
||||||
template <> \
|
template <> \
|
||||||
struct binding_name<T> \
|
struct binding_name<T> \
|
||||||
{ static const char * name = #Name; }; \
|
{ static constexpr char const * name() { return Name; }; }; \
|
||||||
} } /* end namespaces */ \
|
} } /* end namespaces */ \
|
||||||
CEREAL_BIND_TO_ARCHIVES(T);
|
CEREAL_BIND_TO_ARCHIVES(T);
|
||||||
|
|
||||||
@@ -58,7 +63,8 @@ namespace cereal
|
|||||||
{
|
{
|
||||||
if(!ptr)
|
if(!ptr)
|
||||||
{
|
{
|
||||||
//ar (detail::null_ptr());
|
// same behavior as nullptr in memory implementation
|
||||||
|
ar( std::uint32_t(0) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,16 +72,45 @@ namespace cereal
|
|||||||
|
|
||||||
auto binding = bindingMap.find(std::type_index(typeid(*ptr.get())));
|
auto binding = bindingMap.find(std::type_index(typeid(*ptr.get())));
|
||||||
if(binding == bindingMap.end())
|
if(binding == bindingMap.end())
|
||||||
throw cereal::Exception("Trying to serialize unregistered polymorphic type");
|
throw cereal::Exception("Trying to save an unregistered polymorphic type (" + cereal::util::demangle(typeid(*ptr.get()).name()) + ")");
|
||||||
|
|
||||||
binding->second.shared_ptr(&ar, ptr.get());
|
binding->second.shared_ptr(&ar, ptr.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Loading std::shared_ptr, case when user load and allocate for polymorphic types
|
//! Loading std::shared_ptr for polymorphic types
|
||||||
template <class Archive, class T> inline
|
template <class Archive, class T> inline
|
||||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||||
load( Archive & ar, std::shared_ptr<T> & ptr )
|
load( Archive & ar, std::shared_ptr<T> & ptr )
|
||||||
{
|
{
|
||||||
|
std::uint32_t nameid;
|
||||||
|
ar( nameid );
|
||||||
|
|
||||||
|
if(nameid == 0)
|
||||||
|
{
|
||||||
|
ptr.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
if(nameid & detail::msb_32bit)
|
||||||
|
{
|
||||||
|
ar( name );
|
||||||
|
ar.registerPolymorphicName(nameid, name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = ar.getPolymorphicName(nameid);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto & bindingMap = detail::StaticObject<detail::InputBindingMap<Archive>>::getInstance().map;
|
||||||
|
|
||||||
|
auto binding = bindingMap.find(name);
|
||||||
|
if(binding == bindingMap.end())
|
||||||
|
throw cereal::Exception("Trying to load an unregistered polymorphic type (" + name + ")");
|
||||||
|
|
||||||
|
std::shared_ptr<void> result;
|
||||||
|
binding->second.shared_ptr(&ar, result);
|
||||||
|
ptr = std::static_pointer_cast<T>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Saving std::weak_ptr for polymorphic types
|
//! Saving std::weak_ptr for polymorphic types
|
||||||
@@ -83,6 +118,13 @@ namespace cereal
|
|||||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||||
save( Archive & ar, std::weak_ptr<T> const & ptr )
|
save( Archive & ar, std::weak_ptr<T> const & ptr )
|
||||||
{
|
{
|
||||||
|
if(!ptr)
|
||||||
|
{
|
||||||
|
// same behavior as nullptr in memory implementation
|
||||||
|
ar( std::uint32_t(0) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Loading std::weak_ptr for polymorphic types
|
//! Loading std::weak_ptr for polymorphic types
|
||||||
@@ -97,6 +139,13 @@ namespace cereal
|
|||||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||||
save( Archive & ar, std::unique_ptr<T, D> const & ptr )
|
save( Archive & ar, std::unique_ptr<T, D> const & ptr )
|
||||||
{
|
{
|
||||||
|
if(!ptr)
|
||||||
|
{
|
||||||
|
// same behavior as nullptr in memory implementation
|
||||||
|
ar( std::uint32_t(0) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Loading std::unique_ptr, case when user provides load_and_allocate for polymorphic types
|
//! Loading std::unique_ptr, case when user provides load_and_allocate for polymorphic types
|
||||||
|
|||||||
@@ -29,15 +29,23 @@
|
|||||||
#include <cereal/archives/binary.hpp>
|
#include <cereal/archives/binary.hpp>
|
||||||
#include <cereal/types/polymorphic.hpp>
|
#include <cereal/types/polymorphic.hpp>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
struct Base
|
struct Base
|
||||||
{
|
{
|
||||||
virtual void foo() = 0;
|
virtual void foo() = 0;
|
||||||
|
|
||||||
template<class Archive>
|
template<class Archive>
|
||||||
void serialize(Archive & ar)
|
void save(Archive & ar) const
|
||||||
{
|
{
|
||||||
std::cout << "Serializing Base" << std::endl;
|
std::cout << "Saving Base" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void load(Archive & ar)
|
||||||
|
{
|
||||||
|
std::cout << "Loading Base" << std::endl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -46,24 +54,44 @@ struct MyType : public Base
|
|||||||
void foo() {}
|
void foo() {}
|
||||||
|
|
||||||
template<class Archive>
|
template<class Archive>
|
||||||
void serialize(Archive & ar)
|
void save(Archive & ar) const
|
||||||
{
|
{
|
||||||
std::cout << "Serializing MyType" << std::endl;
|
std::cout << "Saving MyType" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Archive>
|
||||||
|
void load(Archive & ar)
|
||||||
|
{
|
||||||
|
std::cout << "Loading MyType" << std::endl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CEREAL_BIND_TO_ARCHIVES(MyType);
|
CEREAL_REGISTER_TYPE(MyType);
|
||||||
|
//CEREAL_REGISTER_TYPE_WITH_NAME(MyType, "cool beans");
|
||||||
|
|
||||||
template <class T> void nop(T&&t) {}
|
template <class T> void nop(T&&t) {}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
std::stringstream stream;
|
{
|
||||||
cereal::BinaryOutputArchive archive(stream);
|
std::ofstream ostream("rtti.txt");
|
||||||
|
cereal::BinaryOutputArchive oarchive(ostream);
|
||||||
|
|
||||||
std::shared_ptr<Base> ptr = std::make_shared<MyType>();
|
std::shared_ptr<Base> ptr = std::make_shared<MyType>();
|
||||||
archive(ptr);
|
|
||||||
|
oarchive(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ifstream istream("rtti.txt");
|
||||||
|
cereal::BinaryInputArchive iarchive(istream);
|
||||||
|
|
||||||
|
std::shared_ptr<Base> ptr;
|
||||||
|
std::shared_ptr<Base> ptr2;
|
||||||
|
|
||||||
|
iarchive(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<int> xxx(nullptr);
|
|
||||||
archive(xxx);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user