mirror of
https://github.com/USCiLab/cereal.git
synced 2025-10-18 01:45:52 +02:00
Empty class elision, and priority_queue unit tests
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,4 +1,4 @@
|
||||
all: test.cpp unittests
|
||||
all: test.cpp
|
||||
g++ -std=c++0x test.cpp -o test -ljsoncpp -I./..
|
||||
|
||||
unittests: unittests.cpp
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
namespace cereal
|
||||
{
|
||||
// ######################################################################
|
||||
class BinaryOutputArchive : public OutputArchive<BinaryOutputArchive>
|
||||
class BinaryOutputArchive : public OutputArchive<BinaryOutputArchive, AllowEmptyClassElision>
|
||||
{
|
||||
public:
|
||||
BinaryOutputArchive(std::ostream & stream) :
|
||||
OutputArchive<BinaryOutputArchive>(this),
|
||||
OutputArchive<BinaryOutputArchive, AllowEmptyClassElision>(this),
|
||||
itsStream(stream)
|
||||
{ }
|
||||
|
||||
@@ -62,11 +62,11 @@ namespace cereal
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
class BinaryInputArchive : public InputArchive<BinaryInputArchive>
|
||||
class BinaryInputArchive : public InputArchive<BinaryInputArchive, AllowEmptyClassElision>
|
||||
{
|
||||
public:
|
||||
BinaryInputArchive(std::istream & stream) :
|
||||
InputArchive<BinaryInputArchive>(this),
|
||||
InputArchive<BinaryInputArchive, AllowEmptyClassElision>(this),
|
||||
itsStream(stream)
|
||||
{ }
|
||||
|
||||
@@ -121,21 +121,23 @@ namespace cereal
|
||||
typename std::enable_if<std::is_array<T>::value, void>::type
|
||||
save(BinaryOutputArchive & ar, T const & array)
|
||||
{
|
||||
ar.save_binary(array, traits::sizeofArray<T>() * sizeof(typename std::remove_all_extents<T>::type));
|
||||
ar.save_binary(array, traits::sizeof_array<T>() * sizeof(typename std::remove_all_extents<T>::type));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename std::enable_if<std::is_array<T>::value, void>::type
|
||||
load(BinaryInputArchive & ar, T & array)
|
||||
{
|
||||
ar.load_binary(array, traits::sizeofArray<T>() * sizeof(typename std::remove_all_extents<T>::type));
|
||||
ar.load_binary(array, traits::sizeof_array<T>() * sizeof(typename std::remove_all_extents<T>::type));
|
||||
}
|
||||
|
||||
template <class Archive, class T>
|
||||
void serialize( Archive & ar, T * & t )
|
||||
CEREAL_ARCHIVE_RESTRICT_SERIALIZE(BinaryInputArchive, BinaryOutputArchive)
|
||||
serialize( Archive & ar, T * & t )
|
||||
{
|
||||
static_assert(!sizeof(T), "Cereal does not support serializing raw pointers - please use a smart pointer");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // CEREAL_BINARY_ARCHIVE_BINARY_ARCHIVE_HPP_
|
||||
|
||||
@@ -37,6 +37,21 @@ namespace cereal
|
||||
|
||||
return H::get( priority_queue );
|
||||
}
|
||||
|
||||
//! Allows access to the protected comparator in priority queue
|
||||
template <class T, class C, class Comp>
|
||||
Comp const & comparator( std::priority_queue<T, C, Comp> const & priority_queue )
|
||||
{
|
||||
struct H : public std::priority_queue<T, C, Comp>
|
||||
{
|
||||
static Comp const & get( std::priority_queue<T, C, Comp> const & pq )
|
||||
{
|
||||
return pq.*(&H::comp);
|
||||
}
|
||||
};
|
||||
|
||||
return H::get( priority_queue );
|
||||
}
|
||||
}
|
||||
|
||||
//! Saving for std::queue to binary
|
||||
@@ -59,6 +74,7 @@ namespace cereal
|
||||
template <class T, class C, class Comp>
|
||||
void save( BinaryOutputArchive & ar, std::priority_queue<T, C, Comp> const & priority_queue )
|
||||
{
|
||||
ar & queue_detail::comparator( priority_queue );
|
||||
ar & queue_detail::container( priority_queue );
|
||||
}
|
||||
|
||||
@@ -66,9 +82,13 @@ namespace cereal
|
||||
template <class T, class C, class Comp>
|
||||
void load( BinaryInputArchive & ar, std::priority_queue<T, C, Comp> & priority_queue )
|
||||
{
|
||||
Comp comparator;
|
||||
ar & comparator;
|
||||
|
||||
C container;
|
||||
ar & container;
|
||||
priority_queue = std::priority_queue<T, C, Comp>( container.begin(), container.end() );
|
||||
|
||||
priority_queue = std::priority_queue<T, C, Comp>( comparator, std::move( container ) );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
|
||||
36
cereal.hpp
36
cereal.hpp
@@ -32,9 +32,11 @@ namespace cereal
|
||||
//! Creates a name value pair for the variable T, using the same name
|
||||
#define CEREAL_NVP(T) ::cereal::make_nvp(#T, T);
|
||||
|
||||
enum Flags { AllowEmptyClassElision = 1 };
|
||||
|
||||
// ######################################################################
|
||||
//! The base output archive class
|
||||
template<class ArchiveType>
|
||||
template<class ArchiveType, uint32_t Flags = 0>
|
||||
class OutputArchive
|
||||
{
|
||||
public:
|
||||
@@ -101,9 +103,19 @@ namespace cereal
|
||||
return *self;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename std::enable_if<(Flags & AllowEmptyClassElision) &&
|
||||
!traits::is_output_serializable<T, ArchiveType>() && traits::is_empty_class<T>(), ArchiveType &>::type
|
||||
operator & (T const & t)
|
||||
{
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! No matching serialization
|
||||
template <class T>
|
||||
typename std::enable_if<!traits::is_output_serializable<T, ArchiveType>(), ArchiveType &>::type
|
||||
typename std::enable_if<!traits::is_output_serializable<T, ArchiveType>() &&
|
||||
(!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !traits::is_empty_class<T>())),
|
||||
ArchiveType &>::type
|
||||
operator & (T const & t)
|
||||
{
|
||||
static_assert(traits::is_output_serializable<T, ArchiveType>(), "Trying to serialize an unserializable type with an output archive.\n\n"
|
||||
@@ -140,7 +152,7 @@ namespace cereal
|
||||
|
||||
// ######################################################################
|
||||
//! The base input archive class
|
||||
template<class ArchiveType>
|
||||
template<class ArchiveType, uint32_t Flags = 0>
|
||||
class InputArchive
|
||||
{
|
||||
public:
|
||||
@@ -186,13 +198,23 @@ namespace cereal
|
||||
return *self;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename std::enable_if<(Flags & AllowEmptyClassElision) &&
|
||||
!traits::is_input_serializable<T, ArchiveType>() && traits::is_empty_class<T>(), ArchiveType &>::type
|
||||
operator & (T const & t)
|
||||
{
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! No matching serialization
|
||||
template <class T>
|
||||
typename std::enable_if<!traits::is_input_serializable<T, ArchiveType>(), ArchiveType &>::type
|
||||
operator & (T & t)
|
||||
typename std::enable_if<!traits::is_input_serializable<T, ArchiveType>() &&
|
||||
(!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !traits::is_empty_class<T>())),
|
||||
ArchiveType &>::type
|
||||
operator & (T const & t)
|
||||
{
|
||||
static_assert(traits::is_input_serializable<T, ArchiveType>(), "Trying to serialize an unserializable type with an input archive.\n\n"
|
||||
"Types must either have a serialize function, or separate load/load functions (but not both).\n"
|
||||
static_assert(traits::is_output_serializable<T, ArchiveType>(), "Trying to serialize an unserializable type with an output archive.\n\n"
|
||||
"Types must either have a serialize function, or separate save/load functions (but not both).\n"
|
||||
"Serialize functions generally have the following signature:\n\n"
|
||||
"template<class Archive>\n"
|
||||
" void serialize(int & ar)\n"
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace cereal
|
||||
|
||||
// ######################################################################
|
||||
// Non Member Serialize
|
||||
template<typename T, typename A> char & serialize(A&, T&);
|
||||
char & serialize(...);
|
||||
template<typename T, typename A>
|
||||
bool constexpr has_non_member_serialize()
|
||||
{ return std::is_void<decltype(serialize(std::declval<A&>(), std::declval<T&>()))>::value; };
|
||||
@@ -43,7 +43,7 @@ namespace cereal
|
||||
|
||||
// ######################################################################
|
||||
// Non Member Load
|
||||
template<typename T, typename A> char & load(A&, T&);
|
||||
char & load(...);
|
||||
template<typename T, typename A>
|
||||
bool constexpr has_non_member_load()
|
||||
{ return std::is_void<decltype(load(std::declval<A&>(), std::declval<T&>()))>::value; };
|
||||
@@ -62,7 +62,7 @@ namespace cereal
|
||||
|
||||
// ######################################################################
|
||||
// Non Member Save
|
||||
template<typename T, typename A> char & save(A&, T const &);
|
||||
char & save(...);
|
||||
template<typename T, typename A>
|
||||
bool constexpr has_non_member_save()
|
||||
{ return std::is_void<decltype(save(std::declval<A&>(), std::declval<T&>()))>::value; };
|
||||
@@ -101,11 +101,31 @@ namespace cereal
|
||||
|
||||
// ######################################################################
|
||||
template <class T>
|
||||
constexpr size_t sizeofArray( size_t rank = std::rank<T>::value )
|
||||
constexpr size_t sizeof_array( size_t rank = std::rank<T>::value )
|
||||
{
|
||||
return rank == 0 ? 1 : std::extent<T>::value * sizeofArray<typename std::remove_extent<T>::type>( rank - 1 );
|
||||
return rank == 0 ? 1 : std::extent<T>::value * sizeof_array<typename std::remove_extent<T>::type>( rank - 1 );
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
namespace detail
|
||||
{
|
||||
template <class T, typename Enable = void>
|
||||
struct is_empty_class_impl
|
||||
{ static constexpr bool value = false; };
|
||||
|
||||
template <class T>
|
||||
struct is_empty_class_impl<T, typename std::enable_if<std::is_class<T>::value>::type>
|
||||
{
|
||||
struct S : T
|
||||
{ uint8_t t; };
|
||||
|
||||
static constexpr bool value = sizeof(S) == sizeof(uint8_t);
|
||||
};
|
||||
}
|
||||
|
||||
template<class T>
|
||||
using is_empty_class = std::integral_constant<bool, detail::is_empty_class_impl<T>::value>;
|
||||
|
||||
// ######################################################################
|
||||
//! A macro to use to restrict which types of archives your serialize function will work for.
|
||||
/*! This requires you to have a template class parameter named Archive and replaces the void return
|
||||
|
||||
11
test.cpp
11
test.cpp
@@ -109,6 +109,15 @@ struct Everything
|
||||
}
|
||||
};
|
||||
|
||||
struct EmptyStruct
|
||||
{
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar)
|
||||
{
|
||||
std::cout << "Side effects up the wazoo" << std::endl;
|
||||
};
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
int main()
|
||||
{
|
||||
@@ -184,6 +193,8 @@ int main()
|
||||
int a2[][2] = {{4, 5}, {6, 7}};
|
||||
archive & a1;
|
||||
archive & a2;
|
||||
EmptyStruct empty;
|
||||
archive & empty;
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user