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./..
|
g++ -std=c++0x test.cpp -o test -ljsoncpp -I./..
|
||||||
|
|
||||||
unittests: unittests.cpp
|
unittests: unittests.cpp
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
namespace cereal
|
namespace cereal
|
||||||
{
|
{
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
class BinaryOutputArchive : public OutputArchive<BinaryOutputArchive>
|
class BinaryOutputArchive : public OutputArchive<BinaryOutputArchive, AllowEmptyClassElision>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BinaryOutputArchive(std::ostream & stream) :
|
BinaryOutputArchive(std::ostream & stream) :
|
||||||
OutputArchive<BinaryOutputArchive>(this),
|
OutputArchive<BinaryOutputArchive, AllowEmptyClassElision>(this),
|
||||||
itsStream(stream)
|
itsStream(stream)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@@ -62,11 +62,11 @@ namespace cereal
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
class BinaryInputArchive : public InputArchive<BinaryInputArchive>
|
class BinaryInputArchive : public InputArchive<BinaryInputArchive, AllowEmptyClassElision>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BinaryInputArchive(std::istream & stream) :
|
BinaryInputArchive(std::istream & stream) :
|
||||||
InputArchive<BinaryInputArchive>(this),
|
InputArchive<BinaryInputArchive, AllowEmptyClassElision>(this),
|
||||||
itsStream(stream)
|
itsStream(stream)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@@ -121,21 +121,23 @@ namespace cereal
|
|||||||
typename std::enable_if<std::is_array<T>::value, void>::type
|
typename std::enable_if<std::is_array<T>::value, void>::type
|
||||||
save(BinaryOutputArchive & ar, T const & array)
|
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>
|
template <class T>
|
||||||
typename std::enable_if<std::is_array<T>::value, void>::type
|
typename std::enable_if<std::is_array<T>::value, void>::type
|
||||||
load(BinaryInputArchive & ar, T & array)
|
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>
|
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");
|
static_assert(!sizeof(T), "Cereal does not support serializing raw pointers - please use a smart pointer");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CEREAL_BINARY_ARCHIVE_BINARY_ARCHIVE_HPP_
|
#endif // CEREAL_BINARY_ARCHIVE_BINARY_ARCHIVE_HPP_
|
||||||
|
|||||||
@@ -37,6 +37,21 @@ namespace cereal
|
|||||||
|
|
||||||
return H::get( priority_queue );
|
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
|
//! Saving for std::queue to binary
|
||||||
@@ -59,6 +74,7 @@ namespace cereal
|
|||||||
template <class T, class C, class Comp>
|
template <class T, class C, class Comp>
|
||||||
void save( BinaryOutputArchive & ar, std::priority_queue<T, C, Comp> const & priority_queue )
|
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 );
|
ar & queue_detail::container( priority_queue );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,9 +82,13 @@ namespace cereal
|
|||||||
template <class T, class C, class Comp>
|
template <class T, class C, class Comp>
|
||||||
void load( BinaryInputArchive & ar, std::priority_queue<T, C, Comp> & priority_queue )
|
void load( BinaryInputArchive & ar, std::priority_queue<T, C, Comp> & priority_queue )
|
||||||
{
|
{
|
||||||
|
Comp comparator;
|
||||||
|
ar & comparator;
|
||||||
|
|
||||||
C container;
|
C container;
|
||||||
ar & 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
|
} // 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
|
//! Creates a name value pair for the variable T, using the same name
|
||||||
#define CEREAL_NVP(T) ::cereal::make_nvp(#T, T);
|
#define CEREAL_NVP(T) ::cereal::make_nvp(#T, T);
|
||||||
|
|
||||||
|
enum Flags { AllowEmptyClassElision = 1 };
|
||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
//! The base output archive class
|
//! The base output archive class
|
||||||
template<class ArchiveType>
|
template<class ArchiveType, uint32_t Flags = 0>
|
||||||
class OutputArchive
|
class OutputArchive
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -101,9 +103,19 @@ namespace cereal
|
|||||||
return *self;
|
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
|
//! No matching serialization
|
||||||
template <class T>
|
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)
|
operator & (T const & t)
|
||||||
{
|
{
|
||||||
static_assert(traits::is_output_serializable<T, ArchiveType>(), "Trying to serialize an unserializable type with an output archive.\n\n"
|
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
|
//! The base input archive class
|
||||||
template<class ArchiveType>
|
template<class ArchiveType, uint32_t Flags = 0>
|
||||||
class InputArchive
|
class InputArchive
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -186,13 +198,23 @@ namespace cereal
|
|||||||
return *self;
|
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
|
//! No matching serialization
|
||||||
template <class T>
|
template <class T>
|
||||||
typename std::enable_if<!traits::is_input_serializable<T, ArchiveType>(), ArchiveType &>::type
|
typename std::enable_if<!traits::is_input_serializable<T, ArchiveType>() &&
|
||||||
operator & (T & t)
|
(!(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"
|
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 load/load functions (but not both).\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"
|
"Serialize functions generally have the following signature:\n\n"
|
||||||
"template<class Archive>\n"
|
"template<class Archive>\n"
|
||||||
" void serialize(int & ar)\n"
|
" void serialize(int & ar)\n"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace cereal
|
|||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
// Non Member Serialize
|
// Non Member Serialize
|
||||||
template<typename T, typename A> char & serialize(A&, T&);
|
char & serialize(...);
|
||||||
template<typename T, typename A>
|
template<typename T, typename A>
|
||||||
bool constexpr has_non_member_serialize()
|
bool constexpr has_non_member_serialize()
|
||||||
{ return std::is_void<decltype(serialize(std::declval<A&>(), std::declval<T&>()))>::value; };
|
{ return std::is_void<decltype(serialize(std::declval<A&>(), std::declval<T&>()))>::value; };
|
||||||
@@ -43,7 +43,7 @@ namespace cereal
|
|||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
// Non Member Load
|
// Non Member Load
|
||||||
template<typename T, typename A> char & load(A&, T&);
|
char & load(...);
|
||||||
template<typename T, typename A>
|
template<typename T, typename A>
|
||||||
bool constexpr has_non_member_load()
|
bool constexpr has_non_member_load()
|
||||||
{ return std::is_void<decltype(load(std::declval<A&>(), std::declval<T&>()))>::value; };
|
{ return std::is_void<decltype(load(std::declval<A&>(), std::declval<T&>()))>::value; };
|
||||||
@@ -62,7 +62,7 @@ namespace cereal
|
|||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
// Non Member Save
|
// Non Member Save
|
||||||
template<typename T, typename A> char & save(A&, T const &);
|
char & save(...);
|
||||||
template<typename T, typename A>
|
template<typename T, typename A>
|
||||||
bool constexpr has_non_member_save()
|
bool constexpr has_non_member_save()
|
||||||
{ return std::is_void<decltype(save(std::declval<A&>(), std::declval<T&>()))>::value; };
|
{ return std::is_void<decltype(save(std::declval<A&>(), std::declval<T&>()))>::value; };
|
||||||
@@ -101,10 +101,30 @@ namespace cereal
|
|||||||
|
|
||||||
// ######################################################################
|
// ######################################################################
|
||||||
template <class T>
|
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.
|
//! A macro to use to restrict which types of archives your serialize function will work for.
|
||||||
|
|||||||
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()
|
int main()
|
||||||
{
|
{
|
||||||
@@ -184,6 +193,8 @@ int main()
|
|||||||
int a2[][2] = {{4, 5}, {6, 7}};
|
int a2[][2] = {{4, 5}, {6, 7}};
|
||||||
archive & a1;
|
archive & a1;
|
||||||
archive & a2;
|
archive & a2;
|
||||||
|
EmptyStruct empty;
|
||||||
|
archive & empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user