mirror of
https://github.com/USCiLab/cereal.git
synced 2025-09-22 21:09:33 +02:00
Renaming load_and_allocate to load_and_construct
Anything associated this that used the verb allocate has been replaced with construct closes #59
This commit is contained in:
parent
4a3c2859e6
commit
30a22fec28
@ -39,11 +39,11 @@ namespace cereal
|
||||
{
|
||||
//! A class that allows cereal to load smart pointers to types that have no default constructor
|
||||
/*! If your class does not have a default constructor, cereal will not be able
|
||||
to load any smart pointers to it unless you overload LoadAndAllocate
|
||||
for your class, and provide an appropriate load_and_allocate method. You can also
|
||||
to load any smart pointers to it unless you overload LoadAndConstruct
|
||||
for your class, and provide an appropriate load_and_construct method. You can also
|
||||
choose to define a member static function instead of specializing this class.
|
||||
|
||||
The specialization of LoadAndAllocate must be placed within the cereal namespace:
|
||||
The specialization of LoadAndConstruct must be placed within the cereal namespace:
|
||||
|
||||
@code{.cpp}
|
||||
struct MyType
|
||||
@ -59,20 +59,20 @@ namespace cereal
|
||||
}
|
||||
};
|
||||
|
||||
// Provide a specialization for LoadAndAllocate for your type
|
||||
// Provide a specialization for LoadAndConstruct for your type
|
||||
namespace cereal
|
||||
{
|
||||
template <> struct LoadAndAllocate<MyType>
|
||||
template <> struct LoadAndConstruct<MyType>
|
||||
{
|
||||
// load_and_allocate will be passed the archive that you will be loading
|
||||
// from as well as an allocate object which you can use as if it were the
|
||||
// load_and_construct will be passed the archive that you will be loading
|
||||
// from as well as a construct object which you can use as if it were the
|
||||
// constructor for your type. cereal will handle all memory management for you.
|
||||
template <class Archive>
|
||||
static void load_and_allocate( Archive & ar, cereal::allocate<MyType> & allocate )
|
||||
static void load_and_construct( Archive & ar, cereal::construct<MyType> & construct )
|
||||
{
|
||||
int x;
|
||||
ar( x );
|
||||
allocate( x );
|
||||
construct( x );
|
||||
}
|
||||
};
|
||||
} // end namespace cereal
|
||||
@ -81,30 +81,30 @@ namespace cereal
|
||||
Please note that just as in using external serialization functions, you cannot get
|
||||
access to non-public members of your class by befriending cereal::access. If you
|
||||
have the ability to modify the class you wish to serialize, it is recommended that you
|
||||
use member serialize functions and a static member load_and_allocate function.
|
||||
use member serialize functions and a static member load_and_construct function.
|
||||
|
||||
@tparam T The type to specialize for
|
||||
@ingroup Access */
|
||||
template <class T>
|
||||
struct LoadAndAllocate
|
||||
struct LoadAndConstruct
|
||||
{
|
||||
//! Called by cereal if no default constructor exists to load and allocate data simultaneously
|
||||
//! Called by cereal if no default constructor exists to load and construct data simultaneously
|
||||
/*! Overloads of this should return a pointer to T and expect an archive as a parameter */
|
||||
static std::false_type load_and_allocate(...)
|
||||
static std::false_type load_and_construct(...)
|
||||
{ return std::false_type(); }
|
||||
};
|
||||
|
||||
// forward decl for allocate
|
||||
// forward decl for construct
|
||||
//! @cond PRIVATE_NEVERDEFINED
|
||||
namespace memory_detail{ template <class Ar, class T> struct LoadAndAllocateLoadWrapper; }
|
||||
namespace memory_detail{ template <class Ar, class T> struct LoadAndConstructLoadWrapper; }
|
||||
//! @endcond
|
||||
|
||||
//! Used to allocate types with no default constructor
|
||||
//! Used to construct types with no default constructor
|
||||
/*! When serializing a type that has no default constructor, cereal
|
||||
will attempt to call either the class static function load_and_allocate
|
||||
or the appropriate template specialization of LoadAndAllocate. cereal
|
||||
will attempt to call either the class static function load_and_construct
|
||||
or the appropriate template specialization of LoadAndConstruct. cereal
|
||||
will pass that function a reference to the archive as well as a reference
|
||||
to an allocate object which should be used to perform the allocation once
|
||||
to a construct object which should be used to perform the allocation once
|
||||
data has been appropriately loaded.
|
||||
|
||||
@code{.cpp}
|
||||
@ -124,21 +124,21 @@ namespace cereal
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
static void load_and_allocate( Archive & ar, cereal::allocate<MyType> & allocate )
|
||||
static void load_and_construct( Archive & ar, cereal::construct<MyType> & construct )
|
||||
{
|
||||
int x, y;
|
||||
ar( x, y );
|
||||
|
||||
// use allocate object to initialize with loaded data
|
||||
allocate( x, y );
|
||||
// use construct object to initialize with loaded data
|
||||
construct( x, y );
|
||||
|
||||
// access to member variables and functions via -> operator
|
||||
ar( allocate->notInConstructor );
|
||||
ar( construct->notInConstructor );
|
||||
|
||||
// could also do the above section by:
|
||||
double z;
|
||||
ar( z );
|
||||
allocate->notInConstructor = z;
|
||||
construct->notInConstructor = z;
|
||||
}
|
||||
};
|
||||
@endcode
|
||||
@ -146,10 +146,10 @@ namespace cereal
|
||||
@tparam T The class type being serialized
|
||||
*/
|
||||
template <class T>
|
||||
class allocate
|
||||
class construct
|
||||
{
|
||||
public:
|
||||
//! Allocate and initialize the type T with the given arguments
|
||||
//! Construct and initialize the type T with the given arguments
|
||||
/*! This will forward all arguments to the underlying type T,
|
||||
calling an appropriate constructor.
|
||||
|
||||
@ -162,7 +162,7 @@ namespace cereal
|
||||
void operator()( Args && ... args )
|
||||
{
|
||||
if( itsValid )
|
||||
throw Exception("Attempting to allocate an already initialized object");
|
||||
throw Exception("Attempting to construct an already initialized object");
|
||||
|
||||
new (itsPtr) T( std::forward<Args>( args )... );
|
||||
itsValid = true;
|
||||
@ -183,7 +183,7 @@ namespace cereal
|
||||
|
||||
//! Returns a raw pointer to the initialized underlying object
|
||||
/*! This is mainly intended for use with passing an instance of
|
||||
an allocated object to cereal::base_class.
|
||||
a constructed object to cereal::base_class.
|
||||
|
||||
It is strongly recommended to avoid using this function in
|
||||
any other circumstance.
|
||||
@ -195,11 +195,11 @@ namespace cereal
|
||||
}
|
||||
|
||||
private:
|
||||
template <class A, class B> friend struct ::cereal::memory_detail::LoadAndAllocateLoadWrapper;
|
||||
template <class A, class B> friend struct ::cereal::memory_detail::LoadAndConstructLoadWrapper;
|
||||
|
||||
allocate( T * p ) : itsPtr( p ), itsValid( false ) {}
|
||||
allocate( allocate const & ) = delete;
|
||||
allocate & operator=( allocate const & ) = delete;
|
||||
construct( T * p ) : itsPtr( p ), itsValid( false ) {}
|
||||
construct( construct const & ) = delete;
|
||||
construct & operator=( construct const & ) = delete;
|
||||
|
||||
T * itsPtr;
|
||||
bool itsValid;
|
||||
@ -263,13 +263,13 @@ namespace cereal
|
||||
{ t.load(ar, version); }
|
||||
|
||||
template <class T>
|
||||
static std::false_type load_and_allocate(...)
|
||||
static std::false_type load_and_construct(...)
|
||||
{ return std::false_type(); }
|
||||
|
||||
template<class T, class Archive> inline
|
||||
static auto load_and_allocate(Archive & ar, ::cereal::allocate<T> & allocate) -> decltype(T::load_and_allocate(ar, allocate))
|
||||
static auto load_and_construct(Archive & ar, ::cereal::construct<T> & construct) -> decltype(T::load_and_construct(ar, construct))
|
||||
{
|
||||
T::load_and_allocate( ar, allocate );
|
||||
T::load_and_construct( ar, construct );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -145,22 +145,22 @@ namespace cereal
|
||||
struct has_non_member_versioned_##name : std::integral_constant<bool, detail::has_non_member_versioned_##name##_impl<T, A>::value> {}
|
||||
|
||||
// ######################################################################
|
||||
// Member load_and_allocate
|
||||
// Member load_and_construct
|
||||
template<typename T, typename A>
|
||||
struct has_member_load_and_allocate :
|
||||
std::integral_constant<bool, std::is_same<decltype( access::load_and_allocate<T>( std::declval<A&>(), std::declval< ::cereal::allocate<T>&>() ) ), void>::value> {};
|
||||
struct has_member_load_and_construct :
|
||||
std::integral_constant<bool, std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value> {};
|
||||
|
||||
// ######################################################################
|
||||
// Non Member load_and_allocate
|
||||
// Non Member load_and_construct
|
||||
template<typename T, typename A>
|
||||
struct has_non_member_load_and_allocate : std::integral_constant<bool,
|
||||
std::is_same<decltype( LoadAndAllocate<T>::load_and_allocate( std::declval<A&>(), std::declval< ::cereal::allocate<T>&>() ) ), void>::value> {};
|
||||
struct has_non_member_load_and_construct : std::integral_constant<bool,
|
||||
std::is_same<decltype( LoadAndConstruct<T>::load_and_construct( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value> {};
|
||||
|
||||
// ######################################################################
|
||||
// Has either a member or non member allocate
|
||||
template<typename T, typename A>
|
||||
struct has_load_and_allocate : std::integral_constant<bool,
|
||||
has_member_load_and_allocate<T, A>::value || has_non_member_load_and_allocate<T, A>::value>
|
||||
struct has_load_and_construct : std::integral_constant<bool,
|
||||
has_member_load_and_construct<T, A>::value || has_non_member_load_and_construct<T, A>::value>
|
||||
{ };
|
||||
|
||||
// ######################################################################
|
||||
@ -580,47 +580,47 @@ namespace cereal
|
||||
// ######################################################################
|
||||
namespace detail
|
||||
{
|
||||
template <class T, class A, bool Member = traits::has_member_load_and_allocate<T, A>::value, bool NonMember = traits::has_non_member_load_and_allocate<T, A>::value>
|
||||
struct Load
|
||||
template <class T, class A, bool Member = traits::has_member_load_and_construct<T, A>::value, bool NonMember = traits::has_non_member_load_and_construct<T, A>::value>
|
||||
struct Construct
|
||||
{
|
||||
static_assert( !sizeof(T), "Cereal detected both member and non member load_and_allocate functions!" );
|
||||
static T * load_andor_allocate( A & /*ar*/, allocate<T> & /*allocate*/ )
|
||||
static_assert( !sizeof(T), "Cereal detected both member and non member load_and_construct functions!" );
|
||||
static T * load_andor_construct( A & /*ar*/, construct<T> & /*construct*/ )
|
||||
{ return nullptr; }
|
||||
};
|
||||
|
||||
template <class T, class A>
|
||||
struct Load<T, A, false, false>
|
||||
struct Construct<T, A, false, false>
|
||||
{
|
||||
static_assert( std::is_default_constructible<T>::value,
|
||||
"Trying to serialize a an object with no default constructor.\n\n"
|
||||
"Types must either be default constructible or define either a member or non member Construct function.\n"
|
||||
"Construct functions generally have the signature:\n\n"
|
||||
"template <class Archive>\n"
|
||||
"static void load_and_allocate(Archive & ar, cereal::allocate<T> & allocate)\n"
|
||||
"static void load_and_construct(Archive & ar, cereal::construct<T> & construct)\n"
|
||||
"{\n"
|
||||
" var a;\n"
|
||||
" ar( a )\n"
|
||||
" allocate( a );\n"
|
||||
" construct( a );\n"
|
||||
"}\n\n" );
|
||||
static T * load_andor_allocate()
|
||||
static T * load_andor_construct()
|
||||
{ return new T(); }
|
||||
};
|
||||
|
||||
template <class T, class A>
|
||||
struct Load<T, A, true, false>
|
||||
struct Construct<T, A, true, false>
|
||||
{
|
||||
static void load_andor_allocate( A & ar, allocate<T> & allocate )
|
||||
static void load_andor_construct( A & ar, construct<T> & construct )
|
||||
{
|
||||
access::load_and_allocate<T>( ar, allocate );
|
||||
access::load_and_construct<T>( ar, construct );
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class A>
|
||||
struct Load<T, A, false, true>
|
||||
struct Construct<T, A, false, true>
|
||||
{
|
||||
static void load_andor_allocate( A & ar, allocate<T> & allocate )
|
||||
static void load_andor_construct( A & ar, construct<T> & construct )
|
||||
{
|
||||
LoadAndAllocate<T>::load_and_allocate( ar, allocate );
|
||||
LoadAndConstruct<T>::load_and_construct( ar, construct );
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
@ -56,26 +56,26 @@ namespace cereal
|
||||
return {std::forward<T>(t)};
|
||||
}
|
||||
|
||||
//! A struct that acts as a wrapper around calling load_andor_allocate
|
||||
/*! The purpose of this is to allow a load_and_allocate call to properly enter into the
|
||||
//! A struct that acts as a wrapper around calling load_andor_construct
|
||||
/*! The purpose of this is to allow a load_and_construct call to properly enter into the
|
||||
'data' NVP of the ptr_wrapper
|
||||
@internal */
|
||||
template <class Archive, class T>
|
||||
struct LoadAndAllocateLoadWrapper
|
||||
struct LoadAndConstructLoadWrapper
|
||||
{
|
||||
LoadAndAllocateLoadWrapper( T * ptr ) :
|
||||
allocate( ptr )
|
||||
LoadAndConstructLoadWrapper( T * ptr ) :
|
||||
construct( ptr )
|
||||
{ }
|
||||
|
||||
inline void serialize( Archive & ar )
|
||||
{
|
||||
::cereal::detail::Load<T, Archive>::load_andor_allocate( ar, allocate );
|
||||
::cereal::detail::Construct<T, Archive>::load_andor_construct( ar, construct );
|
||||
}
|
||||
|
||||
::cereal::allocate<T> allocate;
|
||||
::cereal::construct<T> construct;
|
||||
};
|
||||
|
||||
//! Performs loading and allocation for a shared pointer that is NOT derived from
|
||||
//! Performs loading and construction for a shared pointer that is NOT derived from
|
||||
//! std::enable_shared_from_this
|
||||
/*! This is the typical case, where we simply pass the load wrapper to the
|
||||
archive
|
||||
@ -84,15 +84,15 @@ namespace cereal
|
||||
@param ptr Raw pointer held by the shared_ptr
|
||||
@internal */
|
||||
template <class Archive, class T> inline
|
||||
void loadAndAllocateSharedPtr( Archive & ar, T * ptr, std::false_type /* has_shared_from_this */ )
|
||||
void loadAndConstructSharedPtr( Archive & ar, T * ptr, std::false_type /* has_shared_from_this */ )
|
||||
{
|
||||
memory_detail::LoadAndAllocateLoadWrapper<Archive, T> loadWrapper( ptr );
|
||||
memory_detail::LoadAndConstructLoadWrapper<Archive, T> loadWrapper( ptr );
|
||||
ar( _CEREAL_NVP("data", loadWrapper) );
|
||||
}
|
||||
|
||||
//! Performs loading and allocation for a shared pointer that is derived from
|
||||
//! Performs loading and construction for a shared pointer that is derived from
|
||||
//! std::enable_shared_from_this
|
||||
/*! This special case is necessary because when a user uses load_and_allocate,
|
||||
/*! This special case is necessary because when a user uses load_and_construct,
|
||||
the weak_ptr (or whatever implementation defined variant) that allows
|
||||
enable_shared_from_this to function correctly will not be initialized properly.
|
||||
|
||||
@ -110,9 +110,9 @@ namespace cereal
|
||||
@param ptr Raw pointer held by the shared_ptr
|
||||
@internal */
|
||||
template <class Archive, class T> inline
|
||||
void loadAndAllocateSharedPtr( Archive & ar, T * ptr, std::true_type /* has_shared_from_this */ )
|
||||
void loadAndConstructSharedPtr( Archive & ar, T * ptr, std::true_type /* has_shared_from_this */ )
|
||||
{
|
||||
memory_detail::LoadAndAllocateLoadWrapper<Archive, T> loadWrapper( ptr );
|
||||
memory_detail::LoadAndConstructLoadWrapper<Archive, T> loadWrapper( ptr );
|
||||
|
||||
// typedefs for parent type and storage type
|
||||
using BaseType = typename ::cereal::traits::get_shared_from_this_base<T>::type;
|
||||
@ -143,7 +143,7 @@ namespace cereal
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
}
|
||||
|
||||
//! Loading std::shared_ptr, case when no user load and allocate for non polymorphic types
|
||||
//! Loading std::shared_ptr, case when no user load and construct for non polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
load( Archive & ar, std::shared_ptr<T> & ptr )
|
||||
@ -178,7 +178,7 @@ namespace cereal
|
||||
ar( _CEREAL_NVP("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
}
|
||||
|
||||
//! Loading std::unique_ptr, case when user provides load_and_allocate for non polymorphic types
|
||||
//! Loading std::unique_ptr, case when user provides load_and_construct for non polymorphic types
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
load( Archive & ar, std::unique_ptr<T, D> & ptr )
|
||||
@ -205,10 +205,10 @@ namespace cereal
|
||||
}
|
||||
}
|
||||
|
||||
//! Loading std::shared_ptr, case when user load and allocate (wrapper implementation)
|
||||
//! Loading std::shared_ptr, case when user load and construct (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<traits::has_load_and_allocate<T, Archive>::value, void>::type
|
||||
typename std::enable_if<traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
load( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
@ -243,7 +243,7 @@ namespace cereal
|
||||
ar.registerSharedPointer( id, ptr );
|
||||
|
||||
// Perform the actual loading and allocation
|
||||
memory_detail::loadAndAllocateSharedPtr( ar, ptr.get(), typename ::cereal::traits::has_shared_from_this<T>::type() );
|
||||
memory_detail::loadAndConstructSharedPtr( ar, ptr.get(), typename ::cereal::traits::has_shared_from_this<T>::type() );
|
||||
|
||||
// Mark pointer as valid (initialized)
|
||||
*valid = true;
|
||||
@ -252,10 +252,10 @@ namespace cereal
|
||||
ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id));
|
||||
}
|
||||
|
||||
//! Loading std::shared_ptr, case when no user load and allocate (wrapper implementation)
|
||||
//! Loading std::shared_ptr, case when no user load and construct (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!traits::has_load_and_allocate<T, Archive>::value, void>::type
|
||||
typename std::enable_if<!traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
load( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
@ -266,7 +266,7 @@ namespace cereal
|
||||
|
||||
if( id & detail::msb_32bit )
|
||||
{
|
||||
ptr.reset( detail::Load<T, Archive>::load_andor_allocate() );
|
||||
ptr.reset( detail::Construct<T, Archive>::load_andor_construct() );
|
||||
ar.registerSharedPointer( id, ptr );
|
||||
ar( _CEREAL_NVP("data", *ptr) );
|
||||
}
|
||||
@ -294,10 +294,10 @@ namespace cereal
|
||||
}
|
||||
}
|
||||
|
||||
//! Loading std::unique_ptr, case when user provides load_and_allocate (wrapper implementation)
|
||||
//! Loading std::unique_ptr, case when user provides load_and_construct (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<traits::has_load_and_allocate<T, Archive>::value, void>::type
|
||||
typename std::enable_if<traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
load( Archive & ar, memory_detail::PtrWrapper<std::unique_ptr<T, D> &> & wrapper )
|
||||
{
|
||||
uint8_t isValid;
|
||||
@ -316,7 +316,7 @@ namespace cereal
|
||||
std::unique_ptr<ST> stPtr( new ST() );
|
||||
|
||||
// Use wrapper to enter into "data" nvp of ptr_wrapper
|
||||
memory_detail::LoadAndAllocateLoadWrapper<Archive, T> loadWrapper( reinterpret_cast<T *>( stPtr.get() ) );
|
||||
memory_detail::LoadAndConstructLoadWrapper<Archive, T> loadWrapper( reinterpret_cast<T *>( stPtr.get() ) );
|
||||
|
||||
// Initialize storage
|
||||
ar( _CEREAL_NVP("data", loadWrapper) );
|
||||
@ -328,10 +328,10 @@ namespace cereal
|
||||
ptr.reset( nullptr );
|
||||
}
|
||||
|
||||
//! Loading std::unique_ptr, case when no load_and_allocate (wrapper implementation)
|
||||
//! Loading std::unique_ptr, case when no load_and_construct (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<!traits::has_load_and_allocate<T, Archive>::value, void>::type
|
||||
typename std::enable_if<!traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
load( Archive & ar, memory_detail::PtrWrapper<std::unique_ptr<T, D> &> & wrapper )
|
||||
{
|
||||
uint8_t isValid;
|
||||
@ -341,7 +341,7 @@ namespace cereal
|
||||
|
||||
if( isValid )
|
||||
{
|
||||
ptr.reset( detail::Load<T, Archive>::load_andor_allocate() );
|
||||
ptr.reset( detail::Construct<T, Archive>::load_andor_construct() );
|
||||
ar( *ptr );
|
||||
}
|
||||
else
|
||||
|
@ -133,7 +133,7 @@ namespace cereal
|
||||
@internal */
|
||||
template<class Archive, class T> inline
|
||||
typename std::enable_if<(std::is_default_constructible<T>::value
|
||||
|| traits::has_load_and_allocate<T, Archive>::value)
|
||||
|| traits::has_load_and_construct<T, Archive>::value)
|
||||
&& !std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive & ar, std::shared_ptr<T> & ptr, std::uint32_t const nameid)
|
||||
{
|
||||
@ -151,7 +151,7 @@ namespace cereal
|
||||
@internal */
|
||||
template<class Archive, class T, class D> inline
|
||||
typename std::enable_if<(std::is_default_constructible<T>::value
|
||||
|| traits::has_load_and_allocate<T, Archive>::value)
|
||||
|| traits::has_load_and_construct<T, Archive>::value)
|
||||
&& !std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive & ar, std::unique_ptr<T, D> & ptr, std::uint32_t const nameid)
|
||||
{
|
||||
@ -171,12 +171,12 @@ namespace cereal
|
||||
@internal */
|
||||
template<class Archive, class T> inline
|
||||
typename std::enable_if<(!std::is_default_constructible<T>::value
|
||||
&& !traits::has_load_and_allocate<T, Archive>::value)
|
||||
&& !traits::has_load_and_construct<T, Archive>::value)
|
||||
|| std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive &, std::shared_ptr<T> &, std::uint32_t const nameid)
|
||||
{
|
||||
if(nameid & detail::msb2_32bit)
|
||||
throw cereal::Exception("Cannot load a polymorphic type that is not default constructable and does not have a load_and_allocate function");
|
||||
throw cereal::Exception("Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -188,12 +188,12 @@ namespace cereal
|
||||
@internal */
|
||||
template<class Archive, class T, class D> inline
|
||||
typename std::enable_if<(!std::is_default_constructible<T>::value
|
||||
&& !traits::has_load_and_allocate<T, Archive>::value)
|
||||
&& !traits::has_load_and_construct<T, Archive>::value)
|
||||
|| std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive &, std::unique_ptr<T, D> &, std::uint32_t const nameid)
|
||||
{
|
||||
if(nameid & detail::msb2_32bit)
|
||||
throw cereal::Exception("Cannot load a polymorphic type that is not default constructable and does not have a load_and_allocate function");
|
||||
throw cereal::Exception("Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function");
|
||||
return false;
|
||||
}
|
||||
} // polymorphic_detail
|
||||
@ -360,7 +360,7 @@ namespace cereal
|
||||
binding->second.unique_ptr(&ar, ptr.get());
|
||||
}
|
||||
|
||||
//! Loading std::unique_ptr, case when user provides load_and_allocate for polymorphic types
|
||||
//! Loading std::unique_ptr, case when user provides load_and_construct for polymorphic types
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||
load( Archive & ar, std::unique_ptr<T, D> & ptr )
|
||||
|
14
sandbox.cpp
14
sandbox.cpp
@ -261,27 +261,27 @@ public:
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
static void load_and_allocate( Archive & ar, cereal::allocate<NoDefaultCtor> & allocate )
|
||||
static void load_and_construct( Archive & ar, cereal::construct<NoDefaultCtor> & construct )
|
||||
{
|
||||
int y;
|
||||
ar( y );
|
||||
allocate( y );
|
||||
allocate->z = 33;
|
||||
allocate.ptr()->z = 33;
|
||||
construct( y );
|
||||
construct->z = 33;
|
||||
construct.ptr()->z = 33;
|
||||
}
|
||||
};
|
||||
|
||||
//namespace cereal
|
||||
//{
|
||||
// template <>
|
||||
// struct LoadAndAllocate<NoDefaultCtor>
|
||||
// struct LoadAndConstruct<NoDefaultCtor>
|
||||
// {
|
||||
// template <class Archive>
|
||||
// static void load_and_allocate( Archive & ar, cereal::allocate<NoDefaultCtor> & allocate )
|
||||
// static void load_and_construct( Archive & ar, cereal::construct<NoDefaultCtor> & construct )
|
||||
// {
|
||||
// int y;
|
||||
// ar( y );
|
||||
// allocate( y );
|
||||
// construct( y );
|
||||
// }
|
||||
// };
|
||||
//}
|
||||
|
@ -63,7 +63,7 @@ struct Test
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
static Test * load_and_allocate( Archive & )
|
||||
static Test * load_and_construct( Archive & )
|
||||
{
|
||||
return new Test();
|
||||
}
|
||||
@ -84,12 +84,12 @@ void save( Archive &, Test const & )
|
||||
namespace cereal
|
||||
{
|
||||
template <>
|
||||
struct LoadAndAllocate<Test>
|
||||
struct LoadAndConstruct<Test>
|
||||
{
|
||||
template <class Archive>
|
||||
static void load_and_allocate( Archive &, cereal::allocate<Test> & allocate )
|
||||
static void load_and_construct( Archive &, cereal::construct<Test> & construct )
|
||||
{
|
||||
allocate();
|
||||
construct();
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -130,10 +130,10 @@ int main()
|
||||
typedef Test T;
|
||||
std::cout << std::boolalpha;
|
||||
|
||||
// Test Load and Allocate internal/external
|
||||
std::cout << "\tload_and_allocate" << std::endl;
|
||||
std::cout << cereal::traits::has_member_load_and_allocate<T, Archive>::value << std::endl;
|
||||
std::cout << cereal::traits::has_non_member_load_and_allocate<T, Archive>::value << std::endl;
|
||||
// Test Load and Construct internal/external
|
||||
std::cout << "\tload_and_construct" << std::endl;
|
||||
std::cout << cereal::traits::has_member_load_and_construct<T, Archive>::value << std::endl;
|
||||
std::cout << cereal::traits::has_non_member_load_and_construct<T, Archive>::value << std::endl;
|
||||
|
||||
// serialize
|
||||
std::cout << "\tserialize" << std::endl;
|
||||
@ -172,7 +172,7 @@ int main()
|
||||
|
||||
// array size
|
||||
std::cout << typeid(A).name() << std::endl;
|
||||
std::cout << typeid(cereal::traits::has_load_and_allocate<int, bool>).name() << std::endl;
|
||||
std::cout << typeid(cereal::traits::has_load_and_construct<int, bool>).name() << std::endl;
|
||||
|
||||
// extra testing
|
||||
|
||||
|
@ -1042,20 +1042,20 @@ std::ostream& operator<<(std::ostream& os, MemoryCycle const & s)
|
||||
return os;
|
||||
}
|
||||
|
||||
class MemoryCycleLoadAndAllocate
|
||||
class MemoryCycleLoadAndConstruct
|
||||
{
|
||||
public:
|
||||
MemoryCycleLoadAndAllocate( int v ) :
|
||||
MemoryCycleLoadAndConstruct( int v ) :
|
||||
value( v )
|
||||
{ }
|
||||
|
||||
MemoryCycleLoadAndAllocate( int v,
|
||||
std::weak_ptr<MemoryCycleLoadAndAllocate> p ) :
|
||||
MemoryCycleLoadAndConstruct( int v,
|
||||
std::weak_ptr<MemoryCycleLoadAndConstruct> p ) :
|
||||
value( v ),
|
||||
ptr( p )
|
||||
{ }
|
||||
|
||||
bool operator==( MemoryCycleLoadAndAllocate const & other ) const
|
||||
bool operator==( MemoryCycleLoadAndConstruct const & other ) const
|
||||
{
|
||||
return value == other.value && ptr.lock() == other.ptr.lock();
|
||||
}
|
||||
@ -1067,20 +1067,20 @@ class MemoryCycleLoadAndAllocate
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
static void load_and_allocate( Archive & ar, cereal::allocate<MemoryCycleLoadAndAllocate> & allocate )
|
||||
static void load_and_construct( Archive & ar, cereal::construct<MemoryCycleLoadAndConstruct> & construct )
|
||||
{
|
||||
int value;
|
||||
std::weak_ptr<MemoryCycleLoadAndAllocate> ptr;
|
||||
std::weak_ptr<MemoryCycleLoadAndConstruct> ptr;
|
||||
|
||||
ar( value, ptr );
|
||||
allocate( value, ptr );
|
||||
construct( value, ptr );
|
||||
}
|
||||
|
||||
int value;
|
||||
std::weak_ptr<MemoryCycleLoadAndAllocate> ptr;
|
||||
std::weak_ptr<MemoryCycleLoadAndConstruct> ptr;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, MemoryCycleLoadAndAllocate const & s)
|
||||
std::ostream& operator<<(std::ostream& os, MemoryCycleLoadAndConstruct const & s)
|
||||
{
|
||||
os << "[value: " << s.value << " ptr: " << s.ptr.lock() << "]";
|
||||
return os;
|
||||
@ -1096,7 +1096,7 @@ void test_memory_cycles()
|
||||
{
|
||||
auto o_ptr1 = std::make_shared<MemoryCycle>( random_value<int>(gen) );
|
||||
o_ptr1->ptr = o_ptr1;
|
||||
auto o_ptr2 = std::make_shared<MemoryCycleLoadAndAllocate>( random_value<int>(gen) );
|
||||
auto o_ptr2 = std::make_shared<MemoryCycleLoadAndConstruct>( random_value<int>(gen) );
|
||||
o_ptr2->ptr = o_ptr2;
|
||||
|
||||
std::ostringstream os;
|
||||
@ -1157,11 +1157,11 @@ struct OneLA
|
||||
{ ar( x ); }
|
||||
|
||||
template <class Archive>
|
||||
static void load_and_allocate( Archive & ar, cereal::allocate<OneLA> & allocate )
|
||||
static void load_and_construct( Archive & ar, cereal::construct<OneLA> & construct )
|
||||
{
|
||||
int xx;
|
||||
ar( xx );
|
||||
allocate( xx );
|
||||
construct( xx );
|
||||
}
|
||||
|
||||
bool operator==( OneLA const & other ) const
|
||||
@ -1197,14 +1197,14 @@ std::ostream& operator<<(std::ostream& os, TwoLA const & s)
|
||||
namespace cereal
|
||||
{
|
||||
template <>
|
||||
struct LoadAndAllocate<TwoLA>
|
||||
struct LoadAndConstruct<TwoLA>
|
||||
{
|
||||
template <class Archive>
|
||||
static void load_and_allocate( Archive & ar, cereal::allocate<TwoLA> & allocate )
|
||||
static void load_and_construct( Archive & ar, cereal::construct<TwoLA> & construct )
|
||||
{
|
||||
int xx;
|
||||
ar( xx );
|
||||
allocate( xx );
|
||||
construct( xx );
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1223,11 +1223,11 @@ struct ThreeLA : std::enable_shared_from_this<ThreeLA>
|
||||
{ return x == other.x; }
|
||||
|
||||
template <class Archive>
|
||||
static void load_and_allocate( Archive & ar, cereal::allocate<ThreeLA> & allocate )
|
||||
static void load_and_construct( Archive & ar, cereal::construct<ThreeLA> & construct )
|
||||
{
|
||||
int xx;
|
||||
ar( xx );
|
||||
allocate( xx );
|
||||
construct( xx );
|
||||
}
|
||||
};
|
||||
|
||||
@ -1238,7 +1238,7 @@ std::ostream& operator<<(std::ostream& os, ThreeLA const & s)
|
||||
}
|
||||
|
||||
template <class IArchive, class OArchive>
|
||||
void test_memory_load_allocate()
|
||||
void test_memory_load_construct()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
@ -1290,24 +1290,24 @@ void test_memory_load_allocate()
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( binary_memory_load_allocate )
|
||||
BOOST_AUTO_TEST_CASE( binary_memory_load_construct )
|
||||
{
|
||||
test_memory_load_allocate<cereal::BinaryInputArchive, cereal::BinaryOutputArchive>();
|
||||
test_memory_load_construct<cereal::BinaryInputArchive, cereal::BinaryOutputArchive>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( portable_binary_memory_load_allocate )
|
||||
BOOST_AUTO_TEST_CASE( portable_binary_memory_load_construct )
|
||||
{
|
||||
test_memory_load_allocate<cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive>();
|
||||
test_memory_load_construct<cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( xml_memory_load_allocate )
|
||||
BOOST_AUTO_TEST_CASE( xml_memory_load_construct )
|
||||
{
|
||||
test_memory_load_allocate<cereal::XMLInputArchive, cereal::XMLOutputArchive>();
|
||||
test_memory_load_construct<cereal::XMLInputArchive, cereal::XMLOutputArchive>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( json_memory_load_allocate )
|
||||
BOOST_AUTO_TEST_CASE( json_memory_load_construct )
|
||||
{
|
||||
test_memory_load_allocate<cereal::JSONInputArchive, cereal::JSONOutputArchive>();
|
||||
test_memory_load_construct<cereal::JSONInputArchive, cereal::JSONOutputArchive>();
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
@ -3152,11 +3152,11 @@ struct PolyDerivedLA : public PolyLA
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
static void load_and_allocate( Archive & ar, cereal::allocate<PolyDerivedLA> & allocate )
|
||||
static void load_and_construct( Archive & ar, cereal::construct<PolyDerivedLA> & construct )
|
||||
{
|
||||
int xx;
|
||||
ar( xx );
|
||||
allocate( xx );
|
||||
construct( xx );
|
||||
}
|
||||
|
||||
void foo() {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user