mirror of
https://github.com/USCiLab/cereal.git
synced 2025-10-18 01:45:52 +02:00
Non default constructors now supported by pointers
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
|||||||
CPPFLAGS=-std=c++11 -I./include
|
CPPFLAGS=-std=c++11 -I./include
|
||||||
CC=clang++
|
CC=g++
|
||||||
|
|
||||||
all: unittests sandbox performance
|
all: unittests sandbox performance
|
||||||
|
|
||||||
|
|||||||
@@ -45,9 +45,10 @@ namespace cereal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Loading std::shared_ptr to binary
|
//! Loading std::shared_ptr to binary, case when user load and allocate
|
||||||
template <class T> inline
|
template <class T> inline
|
||||||
void load( BinaryInputArchive & ar, std::shared_ptr<T> & ptr )
|
typename std::enable_if<traits::has_load_and_allocate<T, BinaryInputArchive>(), void>::type
|
||||||
|
load( BinaryInputArchive & ar, std::shared_ptr<T> & ptr )
|
||||||
{
|
{
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
@@ -55,7 +56,27 @@ namespace cereal
|
|||||||
|
|
||||||
if( id & msb_32bit )
|
if( id & msb_32bit )
|
||||||
{
|
{
|
||||||
ptr.reset( new T );
|
ptr.reset( detail::Load<T, BinaryInputArchive>::load_andor_allocate( ar ) );
|
||||||
|
ar.registerSharedPointer(id, ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Loading std::shared_ptr to binary, case when no user load and allocate
|
||||||
|
template <class T> inline
|
||||||
|
typename std::enable_if<!traits::has_load_and_allocate<T, BinaryInputArchive>(), void>::type
|
||||||
|
load( BinaryInputArchive & ar, std::shared_ptr<T> & ptr )
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
|
ar & id;
|
||||||
|
|
||||||
|
if( id & msb_32bit )
|
||||||
|
{
|
||||||
|
ptr.reset( detail::Load<T, BinaryInputArchive>::load_andor_allocate( ar ) );
|
||||||
ar & *ptr;
|
ar & *ptr;
|
||||||
ar.registerSharedPointer(id, ptr);
|
ar.registerSharedPointer(id, ptr);
|
||||||
}
|
}
|
||||||
@@ -89,11 +110,20 @@ namespace cereal
|
|||||||
ar & *ptr;
|
ar & *ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Loading std::unique_ptr from binary
|
//! Loading std::unique_ptr from binary, case when user provides load_and_allocate
|
||||||
template <class T, class D> inline
|
template <class T, class D> inline
|
||||||
void load( BinaryInputArchive & ar, std::unique_ptr<T, D> & ptr )
|
typename std::enable_if<traits::has_load_and_allocate<T, BinaryInputArchive>(), void>::type
|
||||||
|
load( BinaryInputArchive & ar, std::unique_ptr<T, D> & ptr )
|
||||||
{
|
{
|
||||||
ptr.reset(new T);
|
ptr.reset( detail::Load<T, BinaryInputArchive>::load_andor_allocate( ar ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Loading std::unique_ptr from binary, case when no load_and_allocate
|
||||||
|
template <class T, class D> inline
|
||||||
|
typename std::enable_if<!traits::has_load_and_allocate<T, BinaryInputArchive>(), void>::type
|
||||||
|
load( BinaryInputArchive & ar, std::unique_ptr<T, D> & ptr )
|
||||||
|
{
|
||||||
|
ptr.reset( detail::Load<T, BinaryInputArchive>::load_andor_allocate( ar ) );
|
||||||
ar & *ptr;
|
ar & *ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,28 +29,65 @@
|
|||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace cereal
|
namespace cereal
|
||||||
{
|
{
|
||||||
|
template <class T>
|
||||||
|
struct LoadAndAllocate
|
||||||
|
{
|
||||||
|
static void load_and_allocate(...)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
struct access
|
struct access
|
||||||
{
|
{
|
||||||
template<class Archive, class T>
|
template<class Archive, class T> inline
|
||||||
static auto member_serialize(Archive & ar, T & t) -> decltype(t.serialize(ar))
|
static auto member_serialize(Archive & ar, T & t) -> decltype(t.serialize(ar))
|
||||||
{ t.serialize(ar); }
|
{ t.serialize(ar); }
|
||||||
|
|
||||||
template<class Archive, class T>
|
template<class Archive, class T> inline
|
||||||
static auto member_save(Archive & ar, T const & t) -> decltype(t.save(ar))
|
static auto member_save(Archive & ar, T const & t) -> decltype(t.save(ar))
|
||||||
{ t.save(ar); }
|
{ t.save(ar); }
|
||||||
|
|
||||||
template<class Archive, class T>
|
template<class Archive, class T> inline
|
||||||
static auto member_load(Archive & ar, T & t) -> decltype(t.load(ar))
|
static auto member_load(Archive & ar, T & t) -> decltype(t.load(ar))
|
||||||
{ t.load(ar); }
|
{ t.load(ar); }
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
static void load_and_allocate(...)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
template<class T, class Archive> inline
|
||||||
|
static auto load_and_allocate(Archive & ar) -> decltype(T::load_and_allocate(ar))
|
||||||
|
{
|
||||||
|
std::cout << "yo2" << std::endl;
|
||||||
|
return T::load_and_allocate( ar );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace traits
|
namespace traits
|
||||||
{
|
{
|
||||||
template<typename> struct Void { typedef void type; };
|
template<typename> struct Void { typedef void type; };
|
||||||
|
|
||||||
|
// ######################################################################
|
||||||
|
// Member load_and_allocate
|
||||||
|
template<typename T, typename A>
|
||||||
|
bool constexpr has_member_load_and_allocate()
|
||||||
|
{ return std::is_same<decltype( access::load_and_allocate<T>( std::declval<A&>() ) ), T*>::value; };
|
||||||
|
|
||||||
|
// ######################################################################
|
||||||
|
// Non Member load_and_allocate
|
||||||
|
template<typename T, typename A>
|
||||||
|
bool constexpr has_non_member_load_and_allocate()
|
||||||
|
{ return std::is_same<decltype( LoadAndAllocate<T>::load_and_allocate( std::declval<A&>() ) ), T*>::value; };
|
||||||
|
|
||||||
|
// ######################################################################
|
||||||
|
// Has either a member or non member allocate
|
||||||
|
template<typename T, typename A>
|
||||||
|
bool constexpr has_load_and_allocate()
|
||||||
|
{ return has_member_load_and_allocate<T, A>() || has_non_member_load_and_allocate<T, A>(); }
|
||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
// Member Serialize
|
// Member Serialize
|
||||||
template<typename T, class A, typename Sfinae = void>
|
template<typename T, class A, typename Sfinae = void>
|
||||||
@@ -189,6 +226,53 @@ namespace cereal
|
|||||||
#define CEREAL_ARCHIVE_RESTRICT_SERIALIZE(INTYPE, OUTTYPE) \
|
#define CEREAL_ARCHIVE_RESTRICT_SERIALIZE(INTYPE, OUTTYPE) \
|
||||||
typename std::enable_if<std::is_same<Archive, INTYPE>::value || std::is_same<Archive, OUTTYPE>::value, void>::type
|
typename std::enable_if<std::is_same<Archive, INTYPE>::value || std::is_same<Archive, OUTTYPE>::value, void>::type
|
||||||
} // namespace traits
|
} // namespace traits
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <class T, class A, bool Member = traits::has_member_load_and_allocate<T, A>(), bool NonMember = traits::has_non_member_load_and_allocate<T, A>()>
|
||||||
|
struct Load
|
||||||
|
{
|
||||||
|
static_assert( !sizeof(T), "Cereal detected both member and non member load_and_allocate functions!" );
|
||||||
|
static T * load_andor_allocate( A & ar )
|
||||||
|
{ return nullptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class A>
|
||||||
|
struct Load<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 T * load_and_allocate(Archive & ar)\n"
|
||||||
|
"{\n"
|
||||||
|
" var a;\n"
|
||||||
|
" ar & a\n"
|
||||||
|
" return new T(a);\n"
|
||||||
|
"}\n\n" );
|
||||||
|
static T * load_andor_allocate( A & ar )
|
||||||
|
{ return new T(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class A>
|
||||||
|
struct Load<T, A, true, false>
|
||||||
|
{
|
||||||
|
static T * load_andor_allocate( A & ar )
|
||||||
|
{
|
||||||
|
return access::load_and_allocate<T>( ar );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class A>
|
||||||
|
struct Load<T, A, false, true>
|
||||||
|
{
|
||||||
|
static T * load_andor_allocate( A & ar )
|
||||||
|
{
|
||||||
|
return LoadAndAllocate<T>::load_and_allocate( ar );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace detail
|
||||||
} // namespace cereal
|
} // namespace cereal
|
||||||
|
|
||||||
#endif // CEREAL_DETAILS_TRAITS_HPP_
|
#endif // CEREAL_DETAILS_TRAITS_HPP_
|
||||||
|
|||||||
103
sandbox.cpp
103
sandbox.cpp
@@ -172,6 +172,39 @@ struct NonEmptyStruct
|
|||||||
int x, y, z;
|
int x, y, z;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NoDefaultCtor
|
||||||
|
{
|
||||||
|
NoDefaultCtor() = delete;
|
||||||
|
NoDefaultCtor(int x) : y(x)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
int y;
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void serialize( Archive & archive )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//template <class Archive>
|
||||||
|
//static NoDefaultCtor * load_and_allocate( Archive & ar )
|
||||||
|
//{
|
||||||
|
// return new NoDefaultCtor(5);
|
||||||
|
//}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace cereal
|
||||||
|
{
|
||||||
|
template <>
|
||||||
|
struct LoadAndAllocate<NoDefaultCtor>
|
||||||
|
{
|
||||||
|
template <class Archive>
|
||||||
|
static NoDefaultCtor * load_and_allocate( Archive & ar )
|
||||||
|
{
|
||||||
|
return new NoDefaultCtor(5);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@@ -198,20 +231,20 @@ int main()
|
|||||||
// archive & CEREAL_NVP(e_in);
|
// archive & CEREAL_NVP(e_in);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//assert(e_in == e_out);
|
//assert(e_in == e_out);//
|
||||||
|
//
|
||||||
//{
|
//{ //
|
||||||
// std::ofstream os("ptr.txt");
|
// std::ofstream os("pt//r.txt");
|
||||||
// cereal::BinaryOutputArchive archive(os);
|
// cereal::BinaryOutput//Archive archive(os);
|
||||||
// std::shared_ptr<std::shared_ptr<int>> xptr1 = std::make_shared<std::shared_ptr<int>>(std::make_shared<int>(5));
|
// std::shared_ptr<std://:shared_ptr<int>> xptr1 = std::make_shared<std::shared_ptr<int>>(std::make_shared<int>(5));
|
||||||
// std::shared_ptr<int> xptr2 = *xptr1;
|
// std::shared_ptr<int>// xptr2 = *xptr1;
|
||||||
// std::weak_ptr<int> wptr2 = xptr2;
|
// std::weak_ptr<int> w//ptr2 = xptr2;
|
||||||
// std::unique_ptr<Test1> uptr(new Test1);
|
// std::unique_ptr<Test//1> uptr(new Test1);
|
||||||
// uptr->a = 99;
|
// uptr->a = 99; //
|
||||||
// archive & xptr1;
|
// archive & xptr1; //
|
||||||
// archive & xptr2;
|
// archive & xptr2; //
|
||||||
// archive & wptr2;
|
// archive & wptr2; //
|
||||||
// archive & uptr;
|
// archive & uptr; //
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//{
|
//{
|
||||||
@@ -266,22 +299,38 @@ int main()
|
|||||||
// std::cout << std::endl;
|
// std::cout << std::endl;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
Private p;
|
|
||||||
NonEmptyStruct nes;
|
|
||||||
int q;
|
|
||||||
cereal::BinaryOutputArchive archive(std::cout);
|
|
||||||
archive & p;
|
|
||||||
|
|
||||||
|
std::ostringstream os;
|
||||||
|
cereal::BinaryOutputArchive out_archive(os);
|
||||||
|
|
||||||
//cereal::access::member_serialize(archive, p);
|
//in_archive & nd;
|
||||||
//cereal::access::member_serialize(archive, q);
|
|
||||||
//archive & p;
|
|
||||||
//archive & q;
|
|
||||||
//decltype(cereal::access::member_serialize(archive, q)) sss;
|
|
||||||
|
|
||||||
std::cout << cereal::traits::has_member_serialize<Private, cereal::BinaryOutputArchive>() << std::endl;
|
//std::cout << nd->y << std::endl;
|
||||||
std::cout << cereal::traits::is_output_serializable<Private, cereal::BinaryOutputArchive>() << std::endl;
|
|
||||||
std::cout << cereal::traits::has_member_serialize<int, cereal::BinaryOutputArchive>() << std::endl;
|
//auto zxx = cereal::access::load_and_allocate<NonEmptyStruct>( out_archive );
|
||||||
|
//auto xxx = cereal::access::load_and_allocate<NoDefaultCtor>( out_archive );
|
||||||
|
|
||||||
|
//std::cout << cereal::traits::has_member_load_and_allocate<NoDefaultCtor, cereal::BinaryOutputArchive>() << std::endl;
|
||||||
|
//std::cout << cereal::traits::has_member_load_and_allocate<NonEmptyStruct, cereal::BinaryOutputArchive>() << std::endl;
|
||||||
|
//std::cout << cereal::traits::has_member_load_and_allocate<int, cereal::BinaryOutputArchive>() << std::endl;
|
||||||
|
|
||||||
|
//cereal::Construct<int>::Create( out_archive );
|
||||||
|
//cereal::Construct<NoDefaultCtor>::Create( out_archive );
|
||||||
|
|
||||||
|
//std::cout << cereal::traits::has_non_member_load_and_allocate<NoDefaultCtor, cereal::BinaryOutputArchive>() << std::endl;
|
||||||
|
//std::cout << cereal::traits::has_non_member_load_and_allocate<NonEmptyStruct, cereal::BinaryOutputArchive>() << std::endl;
|
||||||
|
//std::cout << cereal::traits::has_non_member_load_and_allocate<int, cereal::BinaryOutputArchive>() << std::endl;
|
||||||
|
|
||||||
|
auto p = std::make_shared<NoDefaultCtor>( 5 );
|
||||||
|
out_archive & p;
|
||||||
|
|
||||||
|
std::istringstream is(os.str());
|
||||||
|
cereal::BinaryInputArchive in_archive(is);
|
||||||
|
|
||||||
|
p->y = 3;
|
||||||
|
|
||||||
|
in_archive & p;
|
||||||
|
std::cout << p->y << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user