Working on type traits compatability for visual studio, not as terrible as I thought

This commit is contained in:
Shane
2013-07-14 19:29:12 -07:00
parent 59c0a9ba8c
commit f2dd043daa
6 changed files with 783 additions and 342 deletions

View File

@@ -30,6 +30,7 @@
#define CEREAL_ACCESS_HPP_ #define CEREAL_ACCESS_HPP_
#include <type_traits> #include <type_traits>
#include <iostream>
namespace cereal namespace cereal
{ {
@@ -86,7 +87,7 @@ namespace cereal
static void load_and_allocate(...) static void load_and_allocate(...)
{ } { }
}; };
//! A class that can be made a friend to give cereal access to non public functions //! A class that can be made a friend to give cereal access to non public functions
/*! If you desire non-public serialization functions within a class, cereal can only /*! If you desire non-public serialization functions within a class, cereal can only
access these if you declare cereal::access a friend. access these if you declare cereal::access a friend.
@@ -112,6 +113,9 @@ namespace cereal
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> inline
// static traits::no member_serialize(...);
template<class Archive, class T> inline 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); }

View File

@@ -40,373 +40,430 @@ namespace cereal
{ {
namespace traits namespace traits
{ {
typedef std::true_type yes;
typedef std::false_type no;
namespace
{
//! Tests whether a type has a const member save function
template <class T, class A>
struct has_const_member_save_impl
{
template <class TT, class AA>
static auto test(int) -> decltype( cereal::access::non_member_save( std::declval<AA&>(), std::declval<TT const &>() ) == 1, yes());
static no test(...);
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value;
};
} // end anon namespace
template <class T, class A>
struct has_const_member_save : std::integral_constant<bool, has_const_member_save_impl<T, A>::value> {};
//! Tests whether a type has a non const member save function
namespace
{
template <class T, class A>
struct has_non_const_member_save_impl
{
template <class TT, class AA>
static auto test(int) -> decltype( cereal::access::non_const_member_save( std::declval<AA&>(), std::declval<TT&>() ) == 1, yes());
static no test(...);
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value;
};
} // end anon namespace
template <class T, class A>
struct has_non_const_member_save : std::integral_constant<bool, has_non_const_member_save_impl<T, A>::value> {};
//! Creates a test for whether a non const member function exists
/*! This should be used to create tests for things that have access
through cereal::access adn begin with the name "member_". name will
be combined with this to create the name of the function that is tested. */
#define CEREAL_MAKE_HAS_MEMBER_TEST(name) \
namespace \
{ \
template <class T, class A> \
struct has_member_##name##_impl \
{ \
template <class TT, class AA> \
static auto test(int) -> decltype( cereal::access::member_##name( std::declval<AA&>(), std::declval<TT&>() ) == 1, yes()); \
template <class, class> \
static no test(...); \
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
}; \
} /* end anon namespace */ \
template <class T, class A> \
struct has_member_##name## : std::integral_constant<bool, has_member_##name##_impl<T, A>::value> {};
template<typename> struct Void { typedef void type; }; template<typename> struct Void { typedef void type; };
// ###################################################################### // ######################################################################
// Member load_and_allocate // Member load_and_allocate
template<typename T, typename A> template<typename T, typename A>
bool constexpr has_member_load_and_allocate() struct has_member_load_and_allocate :
{ return std::is_same<decltype( access::load_and_allocate<T>( std::declval<A&>() ) ), T*>::value; } std::integral_constant<bool, std::is_same<decltype( access::load_and_allocate<T>( std::declval<A&>() ) ), T*>::value> {};
// ###################################################################### // ######################################################################
// Non Member load_and_allocate // Non Member load_and_allocate
template<typename T, typename A> template<typename T, typename A>
bool constexpr has_non_member_load_and_allocate() struct has_non_member_load_and_allocate : std::integral_constant<bool,
{ return std::is_same<decltype( LoadAndAllocate<T>::load_and_allocate( std::declval<A&>() ) ), T*>::value; } std::is_same<decltype( LoadAndAllocate<T>::load_and_allocate( std::declval<A&>() ) ), T*>::value> {};
// ###################################################################### // ######################################################################
// Has either a member or non member allocate // Has either a member or non member allocate
template<typename T, typename A> template<typename T, typename A>
bool constexpr has_load_and_allocate() struct has_load_and_allocate : std::integral_constant<bool,
{ return has_member_load_and_allocate<T, A>() || has_non_member_load_and_allocate<T, A>(); } has_member_load_and_allocate<T, A>::value || has_non_member_load_and_allocate<T, A>::value>
{ };
// ###################################################################### // ######################################################################
// Member Serialize // Member Serialize
template<typename T, class A, typename Sfinae = void> CEREAL_MAKE_HAS_MEMBER_TEST(serialize);
struct has_member_serialize: std::false_type {};
template<typename T, class A>
struct has_member_serialize< T, A,
typename Void<
decltype( access::member_serialize(std::declval<A&>(), std::declval<T&>() ) )
>::type
>: std::true_type {};
// ###################################################################### // ######################################################################
// Non Member Serialize // Non Member Serialize
char & serialize(...); template <class ...> char & serialize(...);
template<typename T, typename A> template<typename T, typename A>
bool constexpr has_non_member_serialize() struct has_non_member_serialize : std::integral_constant<bool,
{ return std::is_void<decltype(serialize(std::declval<A&>(), std::declval<T&>()))>::value; }; std::is_void<decltype(serialize(std::declval<A&>(), std::declval<T&>()))>::value> {};
// ###################################################################### // ######################################################################
// Member Load // Non Member Serialize
template<typename T, class A, typename Sfinae = void> //char & serialize(...);
struct has_member_load: std::false_type {}; //template<typename T, typename A>
//struct has_non_member_serialize : std::integral_constant<bool,
template<typename T, class A> // std::is_void<decltype(serialize(std::declval<A&>(), std::declval<T&>()))>::value>
struct has_member_load< T, A, //{ };
typename Void<
decltype( access::member_load(std::declval<A&>(), std::declval<T&>() ) )
>::type
>: std::true_type {};
// ######################################################################
// Non Member Load
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; };
// ######################################################################
// Member Save
template<typename T, class A, typename Sfinae = void>
struct has_member_save: std::false_type {};
template<typename T, class A>
struct has_member_save< T, A,
typename Void<
decltype( access::member_save(std::declval<A&>(), std::declval<T const &>() ) )
>::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 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>(); }
// ######################################################################
// Returns true if we have an invalid save function (non const)
template <class T, class A>
bool constexpr has_non_const_save()
{ return is_non_const_member_save<T, A>() || is_non_const_non_member_save<T, A>(); }
// ######################################################################
template <class T, class InputArchive, class OutputArchive>
constexpr bool has_member_split()
{ return has_member_load<T, InputArchive>() && has_member_save<T, OutputArchive>(); }
// ######################################################################
template <class T, class InputArchive, class OutputArchive>
constexpr bool has_non_member_split()
{ return has_non_member_load<T, InputArchive>() && has_non_member_save<T, OutputArchive>(); }
// ######################################################################
template <class T, class OutputArchive>
constexpr bool is_output_serializable()
{
static_assert( !has_non_const_save<T, OutputArchive>(),
"cereal detected a non const save. \n "
"save functions must either be const member functions or accept const type aguments if non-member" );
return
has_member_save<T, OutputArchive>() ^
has_non_member_save<T, OutputArchive>() ^
has_member_serialize<T, OutputArchive>() ^
has_non_member_serialize<T, OutputArchive>();
}
// ######################################################################
template <class T, class InputArchive>
constexpr bool is_input_serializable()
{
return
has_member_load<T, InputArchive>() ^
has_non_member_load<T, InputArchive>() ^
has_member_serialize<T, InputArchive>() ^
has_non_member_serialize<T, InputArchive>();
}
// ######################################################################
namespace detail
{
template <class T, class A>
constexpr auto is_specialized_member_serialize() -> bool
{ return !std::is_base_of<std::false_type, specialize<A, T, specialization::member_serialize>>(); }
template <class T, class A>
constexpr auto is_specialized_member_load_save() -> bool
{ return !std::is_base_of<std::false_type, specialize<A, T, specialization::member_load_save>>(); }
template <class T, class A>
constexpr auto is_specialized_non_member_serialize() -> bool
{ return !std::is_base_of<std::false_type, specialize<A, T, specialization::non_member_serialize>>(); }
template <class T, class A>
constexpr auto is_specialized_non_member_load_save() -> bool
{ return !std::is_base_of<std::false_type, specialize<A, T, specialization::non_member_load_save>>(); }
// Considered an error if specialization exists for more than one type
template <class T, class A>
constexpr auto is_specialized_error() -> bool
{
return (is_specialized_member_serialize<T, A>() +
is_specialized_member_load_save<T, A>() +
is_specialized_non_member_serialize<T, A>() +
is_specialized_non_member_load_save<T, A>()) <= 1;
}
} // namespace detail
template <class T, class A>
constexpr auto is_specialized() -> bool
{
static_assert(detail::is_specialized_error<T, A>(), "More than one explicit specialization detected for type.");
return detail::is_specialized_member_serialize<T, A>() ||
detail::is_specialized_member_load_save<T, A>() ||
detail::is_specialized_non_member_serialize<T, A>() ||
detail::is_specialized_non_member_load_save<T, A>();
}
template <class T, class A>
constexpr auto is_specialized_member_serialize() -> bool
{
static_assert( (is_specialized<T, A>() && detail::is_specialized_member_serialize<T, A>() && has_member_serialize<T, A>())
|| !(is_specialized<T, A>() && detail::is_specialized_member_serialize<T, A>()),
"cereal detected member serialization specialization but no member serialize function" );
return is_specialized<T, A>() && detail::is_specialized_member_serialize<T, A>();
}
template <class T, class A>
constexpr auto is_specialized_member_load() -> bool
{
static_assert( (is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>() && has_member_load<T, A>())
|| !(is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>()),
"cereal detected member load specialization but no member load function" );
return is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>();
}
template <class T, class A>
constexpr auto is_specialized_member_save() -> bool
{
static_assert( (is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>() && has_member_save<T, A>())
|| !(is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>()),
"cereal detected member save specialization but no member save function" );
return is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>();
}
template <class T, class A>
constexpr auto is_specialized_non_member_serialize() -> bool
{
static_assert( (is_specialized<T, A>() && detail::is_specialized_non_member_serialize<T, A>() && has_non_member_serialize<T, A>())
|| !(is_specialized<T, A>() && detail::is_specialized_non_member_serialize<T, A>()),
"cereal detected non-member serialization specialization but no non-member serialize function" );
return is_specialized<T, A>() && detail::is_specialized_non_member_serialize<T, A>();
}
template <class T, class A>
constexpr auto is_specialized_non_member_load() -> bool
{
static_assert( (is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>() && has_non_member_load<T, A>())
|| !(is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>()),
"cereal detected non-member load specialization but no non-member load function" );
return is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>();
}
template <class T, class A>
constexpr auto is_specialized_non_member_save() -> bool
{
static_assert( (is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>() && has_non_member_save<T, A>())
|| !(is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>()),
"cereal detected non-member save specialization but no non-member save function" );
return is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>();
}
// ######################################################################
template <class T>
constexpr size_t sizeof_array( size_t rank = std::rank<T>::value )
{
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);
};
struct base_class_id
{
template<class T>
base_class_id(T const * const t) :
type(typeid(T)),
ptr(t),
hash(std::hash<std::type_index>()(typeid(T)) ^ (std::hash<void const *>()(t) << 1))
{ }
bool operator==(base_class_id const & other) const
{ return (type == other.type) && (ptr == other.ptr); }
std::type_index type;
void const * ptr;
size_t hash;
};
struct base_class_id_hash { size_t operator()(base_class_id const & id) const { return id.hash; } };
}
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 function will work for.
/*! This requires you to have a template class parameter named Archive and replaces the void return
type for your function.
INTYPE refers to the input archive type you wish to restrict on.
OUTTYPE refers to the output archive type you wish to restrict on.
For example, if we want to limit a serialize to only work with binary serialization:
@code{.cpp}
template <class Archive>
CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
serialize( Archive & ar, MyCoolType & m )
{
ar & m;
}
@endcode
If you need to do more restrictions in your enable_if, you will need to do this by hand.
*/
#define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \
typename std::enable_if<std::is_same<Archive, INTYPE>::value || std::is_same<Archive, OUTTYPE>::value, void>::type
} // namespace traits } // namespace traits
namespace detail // // ######################################################################
{ // // Member Load
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>()> // template<typename T, class A, typename Sfinae = void>
struct Load // struct has_member_load: std::false_type {};
{
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> // template<typename T, class A>
struct Load<T, A, false, false> // struct has_member_load< T, A,
{ // typename Void<
static_assert( std::is_default_constructible<T>::value, // decltype( access::member_load(std::declval<A&>(), std::declval<T&>() ) )
"Trying to serialize a an object with no default constructor.\n\n" // >::type
"Types must either be default constructible or define either a member or non member Construct function.\n" // >: std::true_type {};
"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> // // Non Member Load
{ // char & load(...);
static T * load_andor_allocate( A & ar ) // template<typename T, typename A>
{ // bool constexpr has_non_member_load()
return access::load_and_allocate<T>( ar ); // { return std::is_void<decltype(load(std::declval<A&>(), std::declval<T&>()))>::value; };
}
};
template <class T, class A> // // ######################################################################
struct Load<T, A, false, true> // // Member Save
{ // template<typename T, class A, typename Sfinae = void>
static T * load_andor_allocate( A & ar ) // struct has_member_save: std::false_type {};
{
return LoadAndAllocate<T>::load_and_allocate( ar ); // template<typename T, class A>
} // struct has_member_save< T, A,
}; // typename Void<
} // namespace detail // decltype( access::member_save(std::declval<A&>(), std::declval<T const &>() ) )
// >::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 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>(); }
// // ######################################################################
// // Returns true if we have an invalid save function (non const)
// template <class T, class A>
// bool constexpr has_non_const_save()
// { return is_non_const_member_save<T, A>() || is_non_const_non_member_save<T, A>(); }
// // ######################################################################
// template <class T, class InputArchive, class OutputArchive>
// constexpr bool has_member_split()
// { return has_member_load<T, InputArchive>() && has_member_save<T, OutputArchive>(); }
// // ######################################################################
// template <class T, class InputArchive, class OutputArchive>
// constexpr bool has_non_member_split()
// { return has_non_member_load<T, InputArchive>() && has_non_member_save<T, OutputArchive>(); }
// // ######################################################################
// template <class T, class OutputArchive>
// constexpr bool is_output_serializable()
// {
// static_assert( !has_non_const_save<T, OutputArchive>(),
// "cereal detected a non const save. \n "
// "save functions must either be const member functions or accept const type aguments if non-member" );
// return
// has_member_save<T, OutputArchive>() ^
// has_non_member_save<T, OutputArchive>() ^
// has_member_serialize<T, OutputArchive>() ^
// has_non_member_serialize<T, OutputArchive>();
// }
// // ######################################################################
// template <class T, class InputArchive>
// constexpr bool is_input_serializable()
// {
// return
// has_member_load<T, InputArchive>() ^
// has_non_member_load<T, InputArchive>() ^
// has_member_serialize<T, InputArchive>() ^
// has_non_member_serialize<T, InputArchive>();
// }
// // ######################################################################
// namespace detail
// {
// template <class T, class A>
// constexpr auto is_specialized_member_serialize() -> bool
// { return !std::is_base_of<std::false_type, specialize<A, T, specialization::member_serialize>>(); }
// template <class T, class A>
// constexpr auto is_specialized_member_load_save() -> bool
// { return !std::is_base_of<std::false_type, specialize<A, T, specialization::member_load_save>>(); }
// template <class T, class A>
// constexpr auto is_specialized_non_member_serialize() -> bool
// { return !std::is_base_of<std::false_type, specialize<A, T, specialization::non_member_serialize>>(); }
// template <class T, class A>
// constexpr auto is_specialized_non_member_load_save() -> bool
// { return !std::is_base_of<std::false_type, specialize<A, T, specialization::non_member_load_save>>(); }
// // Considered an error if specialization exists for more than one type
// template <class T, class A>
// constexpr auto is_specialized_error() -> bool
// {
// return (is_specialized_member_serialize<T, A>() +
// is_specialized_member_load_save<T, A>() +
// is_specialized_non_member_serialize<T, A>() +
// is_specialized_non_member_load_save<T, A>()) <= 1;
// }
// } // namespace detail
// template <class T, class A>
// constexpr auto is_specialized() -> bool
// {
// static_assert(detail::is_specialized_error<T, A>(), "More than one explicit specialization detected for type.");
// return detail::is_specialized_member_serialize<T, A>() ||
// detail::is_specialized_member_load_save<T, A>() ||
// detail::is_specialized_non_member_serialize<T, A>() ||
// detail::is_specialized_non_member_load_save<T, A>();
// }
// template <class T, class A>
// constexpr auto is_specialized_member_serialize() -> bool
// {
// static_assert( (is_specialized<T, A>() && detail::is_specialized_member_serialize<T, A>() && has_member_serialize<T, A>())
// || !(is_specialized<T, A>() && detail::is_specialized_member_serialize<T, A>()),
// "cereal detected member serialization specialization but no member serialize function" );
// return is_specialized<T, A>() && detail::is_specialized_member_serialize<T, A>();
// }
// template <class T, class A>
// constexpr auto is_specialized_member_load() -> bool
// {
// static_assert( (is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>() && has_member_load<T, A>())
// || !(is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>()),
// "cereal detected member load specialization but no member load function" );
// return is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>();
// }
// template <class T, class A>
// constexpr auto is_specialized_member_save() -> bool
// {
// static_assert( (is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>() && has_member_save<T, A>())
// || !(is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>()),
// "cereal detected member save specialization but no member save function" );
// return is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>();
// }
// template <class T, class A>
// constexpr auto is_specialized_non_member_serialize() -> bool
// {
// static_assert( (is_specialized<T, A>() && detail::is_specialized_non_member_serialize<T, A>() && has_non_member_serialize<T, A>())
// || !(is_specialized<T, A>() && detail::is_specialized_non_member_serialize<T, A>()),
// "cereal detected non-member serialization specialization but no non-member serialize function" );
// return is_specialized<T, A>() && detail::is_specialized_non_member_serialize<T, A>();
// }
// template <class T, class A>
// constexpr auto is_specialized_non_member_load() -> bool
// {
// static_assert( (is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>() && has_non_member_load<T, A>())
// || !(is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>()),
// "cereal detected non-member load specialization but no non-member load function" );
// return is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>();
// }
// template <class T, class A>
// constexpr auto is_specialized_non_member_save() -> bool
// {
// static_assert( (is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>() && has_non_member_save<T, A>())
// || !(is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>()),
// "cereal detected non-member save specialization but no non-member save function" );
// return is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>();
// }
// // ######################################################################
// template <class T>
// constexpr size_t sizeof_array( size_t rank = std::rank<T>::value )
// {
// 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);
// };
// struct base_class_id
// {
// template<class T>
// base_class_id(T const * const t) :
// type(typeid(T)),
// ptr(t),
// hash(std::hash<std::type_index>()(typeid(T)) ^ (std::hash<void const *>()(t) << 1))
// { }
// bool operator==(base_class_id const & other) const
// { return (type == other.type) && (ptr == other.ptr); }
// std::type_index type;
// void const * ptr;
// size_t hash;
// };
// struct base_class_id_hash { size_t operator()(base_class_id const & id) const { return id.hash; } };
// }
// 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 function will work for.
// /*! This requires you to have a template class parameter named Archive and replaces the void return
// type for your function.
// INTYPE refers to the input archive type you wish to restrict on.
// OUTTYPE refers to the output archive type you wish to restrict on.
// For example, if we want to limit a serialize to only work with binary serialization:
// @code{.cpp}
// template <class Archive>
// CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
// serialize( Archive & ar, MyCoolType & m )
// {
// ar & m;
// }
// @endcode
// If you need to do more restrictions in your enable_if, you will need to do this by hand.
// */
// #define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \
// typename std::enable_if<std::is_same<Archive, INTYPE>::value || std::is_same<Archive, OUTTYPE>::value, void>::type
//} // 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_

61
sandbox_vs2012.cpp Normal file
View File

@@ -0,0 +1,61 @@
//#include <cereal/access.hpp>
#include <cereal/details/traits.hpp>
#include <iostream>
#include <type_traits>
struct Archive {};
struct Test
{
template <class Archive>
void serialize( Archive & ar )
{
std::cout << "hey there" << std::endl;
}
template <class Archive>
void save( Archive & ar ) const
{
std::cout << "saved by the bell" << std::endl;
}
template <class Archive>
static Test * load_and_allocate( Archive & ar )
{ }
};
template <class Archive>
void serialize( Archive & ar, Test & t )
{ }
//namespace cereal
//{
// template <>
// struct LoadAndAllocate<Test>
// {
// template <class Archive>
// static Test * load_and_allocate( Archive & ar )
// { }
// };
//}
int main()
{
std::cout << std::boolalpha;
//std::cout << cereal::traits::has_member_serialize<Test, Archive>::value << std::endl;
Test t; Archive a;
// Test Load and Allocate internal/external
std::cout << "load_and_allocate" << std::endl;
std::cout << cereal::traits::has_member_load_and_allocate<Test, Archive>::value << std::endl;
std::cout << cereal::traits::has_non_member_load_and_allocate<Test, Archive>::value << std::endl;
// serialize
std::cout << "serialize" << std::endl;
std::cout << cereal::traits::has_member_serialize<Test, Archive>::value << std::endl;
std::cout << cereal::traits::has_non_member_serialize<Test, Archive>::value << std::endl;
return 0;
}

20
vs2012/vs2012.sln Normal file
View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vs2012", "vs2012.vcxproj", "{097C6C5A-7E3A-4831-A32C-B76BC5BD2315}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{097C6C5A-7E3A-4831-A32C-B76BC5BD2315}.Debug|Win32.ActiveCfg = Debug|Win32
{097C6C5A-7E3A-4831-A32C-B76BC5BD2315}.Debug|Win32.Build.0 = Debug|Win32
{097C6C5A-7E3A-4831-A32C-B76BC5BD2315}.Release|Win32.ActiveCfg = Release|Win32
{097C6C5A-7E3A-4831-A32C-B76BC5BD2315}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

128
vs2012/vs2012.vcxproj Normal file
View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{097C6C5A-7E3A-4831-A32C-B76BC5BD2315}</ProjectGuid>
<RootNamespace>vs2012</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120_CTP_Nov2012</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120_CTP_Nov2012</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(SolutionDir)\..\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>$(SolutionDir)\..\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\sandbox_vs2012.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\cereal\access.hpp" />
<ClInclude Include="..\include\cereal\archives\binary.hpp" />
<ClInclude Include="..\include\cereal\archives\json.hpp" />
<ClInclude Include="..\include\cereal\archives\portable_binary.hpp" />
<ClInclude Include="..\include\cereal\archives\xml.hpp" />
<ClInclude Include="..\include\cereal\cereal.hpp" />
<ClInclude Include="..\include\cereal\details\helpers.hpp" />
<ClInclude Include="..\include\cereal\details\polymorphic_impl.hpp" />
<ClInclude Include="..\include\cereal\details\static_object.hpp" />
<ClInclude Include="..\include\cereal\details\traits.hpp" />
<ClInclude Include="..\include\cereal\details\util.hpp" />
<ClInclude Include="..\include\cereal\external\base64.hpp" />
<ClInclude Include="..\include\cereal\external\rapidjson\document.h" />
<ClInclude Include="..\include\cereal\external\rapidjson\filestream.h" />
<ClInclude Include="..\include\cereal\external\rapidjson\genericstream.h" />
<ClInclude Include="..\include\cereal\external\rapidjson\internal\pow10.h" />
<ClInclude Include="..\include\cereal\external\rapidjson\internal\stack.h" />
<ClInclude Include="..\include\cereal\external\rapidjson\internal\strfunc.h" />
<ClInclude Include="..\include\cereal\external\rapidjson\prettywriter.h" />
<ClInclude Include="..\include\cereal\external\rapidjson\rapidjson.h" />
<ClInclude Include="..\include\cereal\external\rapidjson\reader.h" />
<ClInclude Include="..\include\cereal\external\rapidjson\stringbuffer.h" />
<ClInclude Include="..\include\cereal\external\rapidjson\writer.h" />
<ClInclude Include="..\include\cereal\external\rapidxml\rapidxml.hpp" />
<ClInclude Include="..\include\cereal\external\rapidxml\rapidxml_iterators.hpp" />
<ClInclude Include="..\include\cereal\external\rapidxml\rapidxml_print.hpp" />
<ClInclude Include="..\include\cereal\external\rapidxml\rapidxml_utils.hpp" />
<ClInclude Include="..\include\cereal\types\array.hpp" />
<ClInclude Include="..\include\cereal\types\base_class.hpp" />
<ClInclude Include="..\include\cereal\types\bitset.hpp" />
<ClInclude Include="..\include\cereal\types\boost_variant.hpp" />
<ClInclude Include="..\include\cereal\types\chrono.hpp" />
<ClInclude Include="..\include\cereal\types\common.hpp" />
<ClInclude Include="..\include\cereal\types\complex.hpp" />
<ClInclude Include="..\include\cereal\types\deque.hpp" />
<ClInclude Include="..\include\cereal\types\forward_list.hpp" />
<ClInclude Include="..\include\cereal\types\list.hpp" />
<ClInclude Include="..\include\cereal\types\map.hpp" />
<ClInclude Include="..\include\cereal\types\memory.hpp" />
<ClInclude Include="..\include\cereal\types\polymorphic.hpp" />
<ClInclude Include="..\include\cereal\types\queue.hpp" />
<ClInclude Include="..\include\cereal\types\set.hpp" />
<ClInclude Include="..\include\cereal\types\stack.hpp" />
<ClInclude Include="..\include\cereal\types\string.hpp" />
<ClInclude Include="..\include\cereal\types\tuple.hpp" />
<ClInclude Include="..\include\cereal\types\unordered_map.hpp" />
<ClInclude Include="..\include\cereal\types\unordered_set.hpp" />
<ClInclude Include="..\include\cereal\types\utility.hpp" />
<ClInclude Include="..\include\cereal\types\vector.hpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\sandbox_vs2012.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\cereal\access.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\archives\binary.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\archives\json.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\archives\portable_binary.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\archives\xml.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\cereal.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\details\helpers.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\details\polymorphic_impl.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\details\static_object.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\details\traits.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\details\util.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\base64.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidjson\document.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidjson\filestream.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidjson\genericstream.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidjson\internal\pow10.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidjson\internal\stack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidjson\internal\strfunc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidjson\prettywriter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidjson\rapidjson.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidjson\reader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidjson\stringbuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidjson\writer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidxml\rapidxml.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidxml\rapidxml_iterators.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidxml\rapidxml_print.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\external\rapidxml\rapidxml_utils.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\array.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\base_class.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\bitset.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\boost_variant.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\chrono.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\common.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\complex.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\deque.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\forward_list.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\list.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\map.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\memory.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\polymorphic.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\queue.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\set.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\stack.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\string.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\tuple.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\unordered_map.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\unordered_set.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\utility.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\cereal\types\vector.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>