NVP + traits changes

Added more NVP info to types that need it

Adding ability to detect a save function (member or non-member) that is incorrectly declared as non-const.  This is
needed since some nasty compilation errors crop up if you explicitly specify a serialization type and register that type
with an incorrectly constified save function.

So not done yet, but soon in: using a non const save function will trigger a static assertion.

Still need to investigate registering types with explicit disambiguation
This commit is contained in:
Shane Grant
2013-07-04 17:33:13 -07:00
parent f37890f7a5
commit cb6e04c8a6
8 changed files with 122 additions and 16 deletions

View File

@@ -112,6 +112,11 @@ namespace cereal
static auto member_save(Archive & ar, T const & t) -> decltype(t.save(ar))
{ t.save(ar); }
// Used during detection of non const member save
template<class Archive, class T> inline
static auto non_const_member_save(Archive & ar, T & t) -> decltype(t.save(ar))
{ t.save(ar); }
template<class Archive, class T> inline
static auto member_load(Archive & ar, T & t) -> decltype(t.load(ar))
{ t.load(ar); }

View File

@@ -43,13 +43,13 @@ namespace cereal
// 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; };
{ 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; };
{ return std::is_same<decltype( LoadAndAllocate<T>::load_and_allocate( std::declval<A&>() ) ), T*>::value; }
// ######################################################################
// Has either a member or non member allocate
@@ -107,12 +107,51 @@ namespace cereal
>::type
>: std::true_type {};
// ######################################################################
// Non-const Member Save
namespace detail
{
// Detection of any (const or non const) member save
template<typename T, class A, typename Sfinae = void>
struct has_member_save_any: std::false_type {};
template<typename T, class A>
struct has_member_save_any< T, A,
typename Void<
decltype( access::non_const_member_save(std::declval<A&>(), std::declval<typename std::remove_const<T>::type &>() ) )
>::type
>: std::true_type {};
}
// Returns true if we detect a member save function that is not const
template <class T, class A>
constexpr bool is_non_const_member_save()
{
return !has_member_save<T, A>() && detail::has_member_save_any<T, A>();
}
// ######################################################################
// Non Member Save
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; };
{ return std::is_void<decltype(save(std::declval<A&>(), std::declval<T const &>()))>::value; }
// ######################################################################
// Non-const Non member Save
namespace detail
{
template<typename T, typename A>
bool constexpr has_non_member_save_any()
{ return std::is_void<decltype(save(std::declval<A&>(), std::declval<typename std::remove_const<T>::type &>()))>::value; }
}
// Returns true if we detect a non-member save function that is not const
template<typename T, typename A>
bool constexpr is_non_const_non_member_save()
{ return !has_non_member_save<T, A>() && detail::has_non_member_save_any<T, A>(); }
// ######################################################################
template <class T, class InputArchive, class OutputArchive>

View File

@@ -84,7 +84,7 @@ namespace cereal
template <class Archive, class T, class C> inline
void save( Archive & ar, std::queue<T, C> const & queue )
{
ar( queue_detail::container( queue ) );
ar( _CEREAL_NVP("container", queue_detail::container( queue )) );
}
//! Loading for std::queue
@@ -100,8 +100,8 @@ namespace cereal
template <class Archive, class T, class C, class Comp> inline
void save( Archive & ar, std::priority_queue<T, C, Comp> const & priority_queue )
{
ar( queue_detail::comparator( priority_queue ) );
ar( queue_detail::container( priority_queue ) );
ar( _CEREAL_NVP("comparator", queue_detail::comparator( priority_queue )) );
ar( _CEREAL_NVP("container", queue_detail::container( priority_queue )) );
}
//! Loading for std::priority_queue

View File

@@ -54,7 +54,7 @@ namespace cereal
template <class Archive, class T, class C> inline
void save( Archive & ar, std::stack<T, C> const & stack )
{
ar( stack_detail::container( stack ) );
ar( _CEREAL_NVP("container", stack_detail::container( stack )) );
}
//! Loading for std::stack

View File

@@ -41,7 +41,7 @@ namespace cereal
template <class Archive, class ... Types> inline
static void apply( Archive & ar, std::tuple<Types...> & tuple )
{
ar( std::get<Height - 1>( tuple ) );
ar( _CEREAL_NVP("tuple_element", std::get<Height - 1>( tuple )) );
serialize<Height - 1>::template apply( ar, tuple );
}
};
@@ -51,7 +51,7 @@ namespace cereal
struct serialize<0>
{
template <class Archive, class ... Types> inline
static void apply( Archive & ar, std::tuple<Types...> & tuple )
static void apply( Archive &, std::tuple<Types...> & )
{ }
};
}

View File

@@ -36,8 +36,8 @@ namespace cereal
template <class Archive, class T1, class T2> inline
void serialize( Archive & ar, std::pair<T1, T2> & pair )
{
ar( pair.first,
pair.second );
ar( _CEREAL_NVP("first", pair.first),
_CEREAL_NVP("second", pair.second) );
}
} // namespace cereal

View File

@@ -37,6 +37,9 @@
#include <cereal/types/array.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/map.hpp>
#include <cereal/types/utility.hpp>
#include <cereal/types/bitset.hpp>
#include <cereal/types/polymorphic.hpp>
#include <cxxabi.h>
#include <sstream>
@@ -56,6 +59,8 @@ class Base
ar( x );
}
virtual void foo() = 0;
int x;
};
@@ -78,15 +83,18 @@ class Derived : public Base
ar( y );
}
void foo() {}
int y;
};
namespace cereal
{
template <class Archive> struct specialize<Archive, Derived, cereal::specialization::member_load_save> {};
//template <class Archive> struct specialize<Archive, Derived, cereal::specialization::non_member_load_save> {};
}
CEREAL_REGISTER_TYPE(Derived);
// ###################################
struct Test1
{
@@ -213,7 +221,7 @@ struct Everything
struct EmptyStruct
{
template<class Archive>
void serialize(Archive & ar)
void serialize(Archive &)
{
std::cout << "Side effects!" << std::endl;
};
@@ -233,7 +241,7 @@ struct NoDefaultCtor
int y;
template <class Archive>
void serialize( Archive & archive )
void serialize( Archive & )
{
}
@@ -250,7 +258,7 @@ namespace cereal
struct LoadAndAllocate<NoDefaultCtor>
{
template <class Archive>
static NoDefaultCtor * load_and_allocate( Archive & ar )
static NoDefaultCtor * load_and_allocate( Archive & )
{
return new NoDefaultCtor(5);
}

View File

@@ -27,6 +27,7 @@
#include <type_traits>
#include <cereal/archives/binary.hpp>
#include <cereal/archives/xml.hpp>
#include <cereal/types/polymorphic.hpp>
#include <sstream>
#include <fstream>
@@ -123,10 +124,63 @@ struct OurType : public OurBase
}
};
template <class T> void nop(T&&t) {}
struct BaseVirtual
{
int x;
template <class Archive>
void serialize( Archive & ar )
{ ar( x ); }
virtual void foo() = 0;
};
struct DerivedVirtual : public virtual BaseVirtual
{
int y;
virtual void foo() {}
template <class Archive>
void save( Archive & ar ) const
{
ar( cereal::virtual_base_class<BaseVirtual>( this ) );
ar( y );
}
template <class Archive>
void load( Archive & ar )
{
ar( cereal::virtual_base_class<BaseVirtual>( this ) );
ar( y );
}
};
namespace cereal
{
template <class Archive> struct specialize<Archive, DerivedVirtual, cereal::specialization::member_load_save> {};
}
//CEREAL_REGISTER_TYPE(DerivedVirtual);
template <class T> void nop(T&&) {}
int main()
{
std::cout << std::boolalpha;
std::cout << cereal::traits::is_specialized_member_load_save<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
//std::cout << cereal::traits::is_specialized_non_member_serialize<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
std::cout << cereal::traits::is_output_serializable<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
//std::cout << cereal::traits::has_non_member_serialize<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
//std::cout << cereal::traits::is_specialized_member_serialize<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
std::cout << cereal::traits::has_member_serialize<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
std::cout << "sssssssssssss" <<std::endl;
std::cout << cereal::traits::has_member_save<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
std::cout << cereal::traits::is_non_const_member_save<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
std::cout << cereal::traits::detail::has_member_save_any<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
std::cout << cereal::traits::has_non_member_save<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
std::cout << cereal::traits::has_member_serialize<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
std::cout << cereal::traits::has_non_member_serialize<DerivedVirtual, cereal::BinaryOutputArchive>() << std::endl;
{
std::ofstream ostream("rtti.txt");
cereal::BinaryOutputArchive oarchive(ostream);