traits.hpp
Go to the documentation of this file.
/*
Copyright (c) 2014, Randolph Voorhies, Shane Grant
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CEREAL_DETAILS_TRAITS_HPP_
#define CEREAL_DETAILS_TRAITS_HPP_
#ifndef __clang__
#if (__GNUC__ == 4 && __GNUC_MINOR__ <= 7)
#define CEREAL_OLDER_GCC
#endif // gcc 4.7 or earlier
#endif // __clang__
#include <type_traits>
#include <typeindex>
#include "cereal/macros.hpp"
#include "cereal/access.hpp"
namespace cereal
{
namespace traits
{
using yes = std::true_type;
using no = std::false_type;
namespace detail
{
// ######################################################################
template <class T>
struct delay_static_assert : std::false_type {};
// ######################################################################
// SFINAE Helpers
#ifdef CEREAL_OLDER_GCC // when VS supports better SFINAE, we can use this as the default
template<typename> struct Void { typedef void type; };
#endif // CEREAL_OLDER_GCC
enum class sfinae {};
// ######################################################################
// Helper functionality for boolean integral constants and Enable/DisableIf
template <bool H, bool ... T> struct meta_bool_and : std::integral_constant<bool, H && meta_bool_and<T...>::value> {};
template <bool B> struct meta_bool_and<B> : std::integral_constant<bool, B> {};
template <bool H, bool ... T> struct meta_bool_or : std::integral_constant<bool, H || meta_bool_or<T...>::value> {};
template <bool B> struct meta_bool_or<B> : std::integral_constant<bool, B> {};
// workaround needed due to bug in MSVC 2013, see
// http://connect.microsoft.com/VisualStudio/feedback/details/800231/c-11-alias-template-issue
template <bool ... Conditions>
struct EnableIfHelper : std::enable_if<meta_bool_and<Conditions...>::value, sfinae> {};
template <bool ... Conditions>
struct DisableIfHelper : std::enable_if<!meta_bool_or<Conditions...>::value, sfinae> {};
} // namespace detail
static const detail::sfinae sfinae = {};
// ######################################################################
template <bool ... Conditions>
using EnableIf = typename detail::EnableIfHelper<Conditions...>::type;
// ######################################################################
template <bool ... Conditions>
using DisableIf = typename detail::DisableIfHelper<Conditions...>::type;
// ######################################################################
namespace detail
{
template <class InputArchive>
struct get_output_from_input : no
{
static_assert( detail::delay_static_assert<InputArchive>::value,
"Could not find an associated output archive for input archive." );
};
template <class OutputArchive>
struct get_input_from_output : no
{
static_assert( detail::delay_static_assert<OutputArchive>::value,
"Could not find an associated input archive for output archive." );
};
}
#define CEREAL_SETUP_ARCHIVE_TRAITS(InputArchive, OutputArchive) \
namespace cereal { namespace traits { namespace detail { \
template <> struct get_output_from_input<InputArchive> \
{ using type = OutputArchive; }; \
template <> struct get_input_from_output<OutputArchive> \
{ using type = InputArchive; }; } } } /* end namespaces */
// ######################################################################
#define CEREAL_MAKE_VERSIONED_TEST ,0
// ######################################################################
#ifdef CEREAL_OLDER_GCC
#define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned) \
template <class T, class A, class SFINAE = void> \
struct has_member_##test_name : no {}; \
template <class T, class A> \
struct has_member_##test_name<T, A, \
typename detail::Void< decltype( cereal::access::member_##name( std::declval<A&>(), std::declval<T&>() versioned ) ) >::type> : yes {}
#else // NOT CEREAL_OLDER_GCC
#define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned) \
namespace detail \
{ \
template <class T, class A> \
struct has_member_##name##_##versioned##_impl \
{ \
template <class TT, class AA> \
static auto test(int) -> decltype( cereal::access::member_##name( std::declval<AA&>(), std::declval<TT&>() versioned ), yes()); \
template <class, class> \
static no test(...); \
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
}; \
} /* end namespace detail */ \
template <class T, class A> \
struct has_member_##test_name : std::integral_constant<bool, detail::has_member_##name##_##versioned##_impl<T, A>::value> {}
#endif // NOT CEREAL_OLDER_GCC
// ######################################################################
#define CEREAL_MAKE_HAS_NON_MEMBER_TEST(test_name, func, versioned) \
namespace detail \
{ \
template <class T, class A> \
struct has_non_member_##test_name##_impl \
{ \
template <class TT, class AA> \
static auto test(int) -> decltype( func( std::declval<AA&>(), std::declval<TT&>() versioned ), yes()); \
template <class, class> \
static no test( ... ); \
static const bool value = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \
}; \
} /* end namespace detail */ \
template <class T, class A> \
struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> {}
// ######################################################################
// Member Serialize
CEREAL_MAKE_HAS_MEMBER_TEST(serialize, serialize,);
// ######################################################################
// Member Serialize (versioned)
CEREAL_MAKE_HAS_MEMBER_TEST(serialize, versioned_serialize, CEREAL_MAKE_VERSIONED_TEST);
// ######################################################################
// Non Member Serialize
CEREAL_MAKE_HAS_NON_MEMBER_TEST(serialize, CEREAL_SERIALIZE_FUNCTION_NAME,);
// ######################################################################
// Non Member Serialize (versioned)
CEREAL_MAKE_HAS_NON_MEMBER_TEST(versioned_serialize, CEREAL_SERIALIZE_FUNCTION_NAME, CEREAL_MAKE_VERSIONED_TEST);
// ######################################################################
// Member Load
CEREAL_MAKE_HAS_MEMBER_TEST(load, load,);
// ######################################################################
// Member Load (versioned)
CEREAL_MAKE_HAS_MEMBER_TEST(load, versioned_load, CEREAL_MAKE_VERSIONED_TEST);
// ######################################################################
// Non Member Load
CEREAL_MAKE_HAS_NON_MEMBER_TEST(load, CEREAL_LOAD_FUNCTION_NAME,);
// ######################################################################
// Non Member Load (versioned)
CEREAL_MAKE_HAS_NON_MEMBER_TEST(versioned_load, CEREAL_LOAD_FUNCTION_NAME, CEREAL_MAKE_VERSIONED_TEST);
// ######################################################################
#undef CEREAL_MAKE_HAS_NON_MEMBER_TEST
#undef CEREAL_MAKE_HAS_MEMBER_TEST
// ######################################################################
#ifdef CEREAL_OLDER_GCC
#define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned) \
namespace detail \
{ \
template <class T, class A> \
struct has_member_##test_name##_impl \
{ \
template <class TT, class AA, class SFINAE = void> struct test : no {}; \
template <class TT, class AA> \
struct test<TT, AA, \
typename detail::Void< decltype( cereal::access::member_save( std::declval<AA&>(), \
std::declval<TT const &>() versioned ) ) >::type> : yes {}; \
static const bool value = test<T, A>(); \
\
template <class TT, class AA, class SFINAE = void> struct test2 : no {}; \
template <class TT, class AA> \
struct test2<TT, AA, \
typename detail::Void< decltype( cereal::access::member_save_non_const( \
std::declval<AA&>(), \
std::declval<typename std::remove_const<TT>::type&>() versioned ) ) >::type> : yes {}; \
static const bool not_const_type = test2<T, A>(); \
}; \
} /* end namespace detail */
#else /* NOT CEREAL_OLDER_GCC =================================== */
#define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned) \
namespace detail \
{ \
template <class T, class A> \
struct has_member_##test_name##_impl \
{ \
template <class TT, class AA> \
static auto test(int) -> decltype( cereal::access::member_save( std::declval<AA&>(), \
std::declval<TT const &>() versioned ), yes()); \
template <class, class> static no test(...); \
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
\
template <class TT, class AA> \
static auto test2(int) -> decltype( cereal::access::member_save_non_const( \
std::declval<AA &>(), \
std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \
template <class, class> static no test2(...); \
static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \
}; \
} /* end namespace detail */
#endif /* NOT CEREAL_OLDER_GCC */
// ######################################################################
// Member Save
CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(save, )
template <class T, class A>
struct has_member_save : std::integral_constant<bool, detail::has_member_save_impl<T, A>::value>
{
typedef typename detail::has_member_save_impl<T, A> check;
static_assert( check::value || !check::not_const_type,
"cereal detected a non-const save. \n "
"save member functions must always be const" );
};
// ######################################################################
// Member Save (versioned)
CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(versioned_save, CEREAL_MAKE_VERSIONED_TEST)
template <class T, class A>
struct has_member_versioned_save : std::integral_constant<bool, detail::has_member_versioned_save_impl<T, A>::value>
{
typedef typename detail::has_member_versioned_save_impl<T, A> check;
static_assert( check::value || !check::not_const_type,
"cereal detected a versioned non-const save. \n "
"save member functions must always be const" );
};
// ######################################################################
#undef CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL
// ######################################################################
#define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(test_name, versioned) \
namespace detail \
{ \
template <class T, class A> \
struct has_non_member_##test_name##_impl \
{ \
template <class TT, class AA> \
static auto test(int) -> decltype( CEREAL_SAVE_FUNCTION_NAME( \
std::declval<AA&>(), \
std::declval<TT const &>() versioned ), yes()); \
template <class, class> static no test(...); \
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
\
template <class TT, class AA> \
static auto test2(int) -> decltype( CEREAL_SAVE_FUNCTION_NAME( \
std::declval<AA &>(), \
std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \
template <class, class> static no test2(...); \
static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \
}; \
} /* end namespace detail */ \
\
template <class T, class A> \
struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> \
{ \
using check = typename detail::has_non_member_##test_name##_impl<T, A>; \
static_assert( check::value || !check::not_const_type, \
"cereal detected a non-const type parameter in non-member " #test_name ". \n " \
#test_name " non-member functions must always pass their types as const" ); \
};
// ######################################################################
// Non Member Save
CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(save, )
// ######################################################################
// Non Member Save (versioned)
CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(versioned_save, CEREAL_MAKE_VERSIONED_TEST)
// ######################################################################
#undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST
// ######################################################################
// Minimal Utilities
namespace detail
{
// Determines if the provided type is an std::string
template <class> struct is_string : std::false_type {};
template <class CharT, class Traits, class Alloc>
struct is_string<std::basic_string<CharT, Traits, Alloc>> : std::true_type {};
}
// Determines if the type is valid for use with a minimal serialize function
template <class T>
struct is_minimal_type : std::integral_constant<bool,
detail::is_string<T>::value || std::is_arithmetic<T>::value> {};
// ######################################################################
#ifdef CEREAL_OLDER_GCC
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned) \
namespace detail \
{ \
template <class T, class A> \
struct has_member_##test_name##_impl \
{ \
template <class TT, class AA, class SFINAE = void> struct test : no {}; \
template <class TT, class AA> \
struct test<TT, AA, typename detail::Void< decltype( \
cereal::access::member_save_minimal( std::declval<AA const &>(), \
std::declval<TT const &>() versioned ) ) >::type> : yes {}; \
\
static const bool value = test<T, A>(); \
\
template <class TT, class AA, class SFINAE = void> struct test2 : no {}; \
template <class TT, class AA> \
struct test2<TT, AA, typename detail::Void< decltype( \
cereal::access::member_save_minimal_non_const( std::declval<AA const &>(), \
std::declval<typename std::remove_const<TT>::type&>() versioned ) ) >::type> : yes {}; \
static const bool not_const_type = test2<T, A>(); \
\
static const bool valid = value || !not_const_type; \
}; \
} /* end namespace detail */
#else /* NOT CEREAL_OLDER_GCC =================================== */
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned) \
namespace detail \
{ \
template <class T, class A> \
struct has_member_##test_name##_impl \
{ \
template <class TT, class AA> \
static auto test(int) -> decltype( cereal::access::member_save_minimal( \
std::declval<AA const &>(), \
std::declval<TT const &>() versioned ), yes()); \
template <class, class> static no test(...); \
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
\
template <class TT, class AA> \
static auto test2(int) -> decltype( cereal::access::member_save_minimal_non_const( \
std::declval<AA const &>(), \
std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \
template <class, class> static no test2(...); \
static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \
\
static const bool valid = value || !not_const_type; \
}; \
} /* end namespace detail */
#endif // NOT CEREAL_OLDER_GCC
// ######################################################################
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(test_name, versioned) \
namespace detail \
{ \
template <class T, class A, bool Valid> \
struct get_member_##test_name##_type { using type = void; }; \
\
template <class T, class A> \
struct get_member_##test_name##_type<T, A, true> \
{ \
using type = decltype( cereal::access::member_save_minimal( std::declval<A const &>(), \
std::declval<T const &>() versioned ) ); \
}; \
} /* end namespace detail */
// ######################################################################
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(test_name) \
template <class T, class A> \
struct has_member_##test_name : std::integral_constant<bool, detail::has_member_##test_name##_impl<T, A>::value> \
{ \
using check = typename detail::has_member_##test_name##_impl<T, A>; \
static_assert( check::valid, \
"cereal detected a non-const member " #test_name ". \n " \
#test_name " member functions must always be const" ); \
\
using type = typename detail::get_member_##test_name##_type<T, A, check::value>::type; \
static_assert( (check::value && is_minimal_type<type>::value) || !check::value, \
"cereal detected a member " #test_name " with an invalid return type. \n " \
"return type must be arithmetic or string" ); \
};
// ######################################################################
// Member Save Minimal
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(save_minimal, )
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(save_minimal, )
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(save_minimal)
// ######################################################################
// Member Save Minimal (versioned)
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(versioned_save_minimal)
// ######################################################################
#undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL
#undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL
#undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST
// ######################################################################
#define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(test_name, versioned) \
namespace detail \
{ \
template <class T, class A> \
struct has_non_member_##test_name##_impl \
{ \
template <class TT, class AA> \
static auto test(int) -> decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( \
std::declval<AA const &>(), \
std::declval<TT const &>() versioned ), yes()); \
template <class, class> static no test(...); \
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
\
template <class TT, class AA> \
static auto test2(int) -> decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( \
std::declval<AA const &>(), \
std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \
template <class, class> static no test2(...); \
static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \
\
static const bool valid = value || !not_const_type; \
}; \
\
template <class T, class A, bool Valid> \
struct get_non_member_##test_name##_type { using type = void; }; \
\
template <class T, class A> \
struct get_non_member_##test_name##_type <T, A, true> \
{ \
using type = decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( std::declval<A const &>(), \
std::declval<T const &>() versioned ) ); \
}; \
} /* end namespace detail */ \
\
template <class T, class A> \
struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> \
{ \
using check = typename detail::has_non_member_##test_name##_impl<T, A>; \
static_assert( check::valid, \
"cereal detected a non-const type parameter in non-member " #test_name ". \n " \
#test_name " non-member functions must always pass their types as const" ); \
\
using type = typename detail::get_non_member_##test_name##_type<T, A, check::value>::type; \
static_assert( (check::value && is_minimal_type<type>::value) || !check::value, \
"cereal detected a non-member " #test_name " with an invalid return type. \n " \
"return type must be arithmetic or string" ); \
};
// ######################################################################
// Non-Member Save Minimal
CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(save_minimal, )
// ######################################################################
// Non-Member Save Minimal (versioned)
CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
// ######################################################################
#undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST
// ######################################################################
// Load Minimal Utilities
namespace detail
{
struct NoConvertBase {};
template <class Source>
struct NoConvertConstRef : NoConvertBase
{
using type = Source;
template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
operator Dest () = delete;
template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
operator Dest const & ();
};
template <class Source>
struct NoConvertRef : NoConvertBase
{
using type = Source;
template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
operator Dest () = delete;
#ifdef __clang__
template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
operator Dest const & () = delete;
#endif // __clang__
template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
operator Dest & ();
};
struct AnyConvert
{
template <class Dest>
operator Dest & ();
template <class Dest>
operator Dest const & () const;
};
} // namespace detail
// ######################################################################
#ifdef CEREAL_OLDER_GCC
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned) \
namespace detail \
{ \
template <class T, class A, class SFINAE = void> struct has_member_##test_name##_impl : no {}; \
template <class T, class A> \
struct has_member_##test_name##_impl<T, A, typename detail::Void< decltype( \
cereal::access::member_load_minimal( std::declval<A const &>(), \
std::declval<T &>(), AnyConvert() versioned ) ) >::type> : yes {}; \
\
template <class T, class A, class U, class SFINAE = void> struct has_member_##test_name##_type_impl : no {}; \
template <class T, class A, class U> \
struct has_member_##test_name##_type_impl<T, A, U, typename detail::Void< decltype( \
cereal::access::member_load_minimal( std::declval<A const &>(), \
std::declval<T &>(), NoConvertConstRef<U>() versioned ) ) >::type> : yes {}; \
} /* end namespace detail */
#else /* NOT CEREAL_OLDER_GCC =================================== */
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned) \
namespace detail \
{ \
template <class T, class A> \
struct has_member_##test_name##_impl \
{ \
template <class TT, class AA> \
static auto test(int) -> decltype( cereal::access::member_load_minimal( \
std::declval<AA const &>(), \
std::declval<TT &>(), AnyConvert() versioned ), yes()); \
template <class, class> static no test(...); \
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
}; \
template <class T, class A, class U> \
struct has_member_##test_name##_type_impl \
{ \
template <class TT, class AA, class UU> \
static auto test(int) -> decltype( cereal::access::member_load_minimal( \
std::declval<AA const &>(), \
std::declval<TT &>(), NoConvertConstRef<UU>() versioned ), yes()); \
template <class, class, class> static no test(...); \
static const bool value = std::is_same<decltype(test<T, A, U>(0)), yes>::value; \
\
}; \
} /* end namespace detail */
#endif // NOT CEREAL_OLDER_GCC
// ######################################################################
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_test_name, save_test_name, save_test_prefix, versioned) \
namespace detail \
{ \
template <class T, class A, bool Valid> \
struct has_member_##load_test_name##_wrapper : std::false_type {}; \
\
template <class T, class A> \
struct has_member_##load_test_name##_wrapper<T, A, true> \
{ \
using AOut = typename detail::get_output_from_input<A>::type; \
\
static_assert( has_member_##save_test_prefix##_minimal<T, AOut>::value, \
"cereal detected member " #load_test_name " but no valid member " #save_test_name ". \n " \
"cannot evaluate correctness of " #load_test_name " without valid " #save_test_name "." ); \
\
using SaveType = typename detail::get_member_##save_test_prefix##_minimal_type<T, AOut, true>::type; \
const static bool value = has_member_##load_test_name##_impl<T, A>::value; \
const static bool valid = has_member_##load_test_name##_type_impl<T, A, SaveType>::value; \
\
static_assert( valid || !value, "cereal detected different or invalid types in corresponding member " \
#load_test_name " and " #save_test_name " functions. \n " \
"the paramater to " #load_test_name " must be a constant reference to the type that " \
#save_test_name " returns." ); \
}; \
} /* end namespace detail */
// ######################################################################
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_test_name, load_test_prefix) \
template <class T, class A> \
struct has_member_##load_test_prefix##_minimal : std::integral_constant<bool, \
detail::has_member_##load_test_name##_wrapper<T, A, detail::has_member_##load_test_name##_impl<T, A>::value>::value> {};
// ######################################################################
// Member Load Minimal
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(load_minimal, )
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_minimal, save_minimal, save, )
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_minimal, load)
// ######################################################################
// Member Load Minimal (versioned)
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(versioned_load_minimal, CEREAL_MAKE_VERSIONED_TEST)
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(versioned_load_minimal, versioned_save_minimal, versioned_save, CEREAL_MAKE_VERSIONED_TEST)
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_load)
// ######################################################################
#undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL
#undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL
#undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST
// ######################################################################
// Non-Member Load Minimal
namespace detail
{
#ifdef CEREAL_OLDER_GCC
void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(); // prevents nonsense complaining about not finding this
void CEREAL_SAVE_MINIMAL_FUNCTION_NAME();
#endif // CEREAL_OLDER_GCC
} // namespace detail
// ######################################################################
#define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned) \
namespace detail \
{ \
template <class T, class A, class U = void> \
struct has_non_member_##test_name##_impl \
{ \
template <class TT, class AA> \
static auto test(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
std::declval<AA const &>(), std::declval<TT&>(), AnyConvert() versioned ), yes() ); \
template <class, class> static no test( ... ); \
static const bool exists = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \
\
template <class TT, class AA, class UU> \
static auto test2(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
std::declval<AA const &>(), std::declval<TT&>(), NoConvertConstRef<UU>() versioned ), yes() ); \
template <class, class, class> static no test2( ... ); \
static const bool valid = std::is_same<decltype( test2<T, A, U>( 0 ) ), yes>::value; \
\
template <class TT, class AA> \
static auto test3(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
std::declval<AA const &>(), NoConvertRef<TT>(), AnyConvert() versioned ), yes() ); \
template <class, class> static no test3( ... ); \
static const bool const_valid = std::is_same<decltype( test3<T, A>( 0 ) ), yes>::value; \
}; \
\
template <class T, class A, bool Valid> \
struct has_non_member_##test_name##_wrapper : std::false_type {}; \
\
template <class T, class A> \
struct has_non_member_##test_name##_wrapper<T, A, true> \
{ \
using AOut = typename detail::get_output_from_input<A>::type; \
\
static_assert( detail::has_non_member_##save_name##_impl<T, AOut>::valid, \
"cereal detected non-member " #test_name " but no valid non-member " #save_name ". \n " \
"cannot evaluate correctness of " #test_name " without valid " #save_name "." ); \
\
using SaveType = typename detail::get_non_member_##save_name##_type<T, AOut, true>::type; \
using check = has_non_member_##test_name##_impl<T, A, SaveType>; \
static const bool value = check::exists; \
\
static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member " \
#test_name " and " #save_name " functions. \n " \
"the paramater to " #test_name " must be a constant reference to the type that " #save_name " returns." ); \
}; \
} /* namespace detail */ \
\
template <class T, class A> \
struct has_non_member_##test_name : std::integral_constant<bool, \
detail::has_non_member_##test_name##_wrapper<T, A, detail::has_non_member_##test_name##_impl<T, A>::exists>::value> {};
// ######################################################################
// Non-Member Load Minimal
CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(load_minimal, save_minimal, )
// ######################################################################
// Non-Member Load Minimal (versioned)
CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
// ######################################################################
#undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST
// ######################################################################
namespace detail
{
// const stripped away before reaching here, prevents errors on conversion from
// construct<const T> to construct<T>
template<typename T, typename A>
struct has_member_load_and_construct_impl : std::integral_constant<bool,
std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
{ };
template<typename T, typename A>
struct has_member_versioned_load_and_construct_impl : std::integral_constant<bool,
std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>(), 0 ) ), void>::value>
{ };
} // namespace detail
template<typename T, typename A>
struct has_member_load_and_construct : detail::has_member_load_and_construct_impl<typename std::remove_const<T>::type, A>
{ };
template<typename T, typename A>
struct has_member_versioned_load_and_construct : detail::has_member_versioned_load_and_construct_impl<typename std::remove_const<T>::type, A>
{ };
// ######################################################################
#define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(test_name, versioned) \
namespace detail \
{ \
template <class T, class A> \
struct has_non_member_##test_name##_impl \
{ \
template <class TT, class AA> \
static auto test(int) -> decltype( LoadAndConstruct<TT>::load_and_construct( \
std::declval<AA&>(), std::declval< ::cereal::construct<TT>&>() versioned ), yes()); \
template <class, class> \
static no test( ... ); \
static const bool value = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \
}; \
} /* end namespace detail */ \
template <class T, class A> \
struct has_non_member_##test_name : \
std::integral_constant<bool, detail::has_non_member_##test_name##_impl<typename std::remove_const<T>::type, A>::value> {};
// ######################################################################
CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(load_and_construct, )
// ######################################################################
CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(versioned_load_and_construct, CEREAL_MAKE_VERSIONED_TEST)
// ######################################################################
template<typename T, typename A>
struct has_load_and_construct : std::integral_constant<bool,
has_member_load_and_construct<T, A>::value || has_non_member_load_and_construct<T, A>::value ||
has_member_versioned_load_and_construct<T, A>::value || has_non_member_versioned_load_and_construct<T, A>::value>
{ };
// ######################################################################
#undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST
// ######################################################################
// End of serialization existence tests
#undef CEREAL_MAKE_VERSIONED_TEST
// ######################################################################
template <class T, class InputArchive, class OutputArchive>
struct has_member_split : std::integral_constant<bool,
(has_member_load<T, InputArchive>::value && has_member_save<T, OutputArchive>::value) ||
(has_member_versioned_load<T, InputArchive>::value && has_member_versioned_save<T, OutputArchive>::value)> {};
// ######################################################################
template <class T, class InputArchive, class OutputArchive>
struct has_non_member_split : std::integral_constant<bool,
(has_non_member_load<T, InputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
(has_non_member_versioned_load<T, InputArchive>::value && has_non_member_versioned_save<T, OutputArchive>::value)> {};
// ######################################################################
template <class T, class OutputArchive>
struct has_invalid_output_versioning : std::integral_constant<bool,
(has_member_versioned_save<T, OutputArchive>::value && has_member_save<T, OutputArchive>::value) ||
(has_non_member_versioned_save<T, OutputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
(has_member_versioned_serialize<T, OutputArchive>::value && has_member_serialize<T, OutputArchive>::value) ||
(has_non_member_versioned_serialize<T, OutputArchive>::value && has_non_member_serialize<T, OutputArchive>::value) ||
(has_member_versioned_save_minimal<T, OutputArchive>::value && has_member_save_minimal<T, OutputArchive>::value) ||
(has_non_member_versioned_save_minimal<T, OutputArchive>::value && has_non_member_save_minimal<T, OutputArchive>::value)> {};
// ######################################################################
template <class T, class InputArchive>
struct has_invalid_input_versioning : std::integral_constant<bool,
(has_member_versioned_load<T, InputArchive>::value && has_member_load<T, InputArchive>::value) ||
(has_non_member_versioned_load<T, InputArchive>::value && has_non_member_load<T, InputArchive>::value) ||
(has_member_versioned_serialize<T, InputArchive>::value && has_member_serialize<T, InputArchive>::value) ||
(has_non_member_versioned_serialize<T, InputArchive>::value && has_non_member_serialize<T, InputArchive>::value) ||
(has_member_versioned_load_minimal<T, InputArchive>::value && has_member_load_minimal<T, InputArchive>::value) ||
(has_non_member_versioned_load_minimal<T, InputArchive>::value && has_non_member_load_minimal<T, InputArchive>::value)> {};
// ######################################################################
namespace detail
{
#define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name) \
template <class T, class A> \
struct is_specialized_##name : std::integral_constant<bool, \
!std::is_base_of<std::false_type, specialize<A, T, specialization::name>>::value> {}
CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_serialize);
CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save);
CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save_minimal);
CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_serialize);
CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save);
CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save_minimal);
#undef CEREAL_MAKE_IS_SPECIALIZED_IMPL
template <class T, class A>
struct count_specializations : std::integral_constant<int,
is_specialized_member_serialize<T, A>::value +
is_specialized_member_load_save<T, A>::value +
is_specialized_member_load_save_minimal<T, A>::value +
is_specialized_non_member_serialize<T, A>::value +
is_specialized_non_member_load_save<T, A>::value +
is_specialized_non_member_load_save_minimal<T, A>::value> {};
} // namespace detail
template <class T, class A>
struct is_specialized : std::integral_constant<bool,
detail::is_specialized_member_serialize<T, A>::value ||
detail::is_specialized_member_load_save<T, A>::value ||
detail::is_specialized_member_load_save_minimal<T, A>::value ||
detail::is_specialized_non_member_serialize<T, A>::value ||
detail::is_specialized_non_member_load_save<T, A>::value ||
detail::is_specialized_non_member_load_save_minimal<T, A>::value>
{
static_assert(detail::count_specializations<T, A>::value <= 1, "More than one explicit specialization detected for type.");
};
#define CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, print_name, spec_name) \
static_assert( (is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value && \
(has_##name<T, A>::value || has_##versioned_name<T, A>::value)) \
|| !(is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value), \
"cereal detected " #print_name " specialization but no " #print_name " serialize function" )
#define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name) \
template <class T, class A> \
struct is_specialized_##name : std::integral_constant<bool, \
is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \
{ CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, name, spec_name); }; \
template <class T, class A> \
struct is_specialized_##versioned_name : std::integral_constant<bool, \
is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \
{ CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, versioned_name, spec_name); }
CEREAL_MAKE_IS_SPECIALIZED(member_serialize, member_versioned_serialize, member_serialize);
CEREAL_MAKE_IS_SPECIALIZED(non_member_serialize, non_member_versioned_serialize, non_member_serialize);
CEREAL_MAKE_IS_SPECIALIZED(member_save, member_versioned_save, member_load_save);
CEREAL_MAKE_IS_SPECIALIZED(non_member_save, non_member_versioned_save, non_member_load_save);
CEREAL_MAKE_IS_SPECIALIZED(member_load, member_versioned_load, member_load_save);
CEREAL_MAKE_IS_SPECIALIZED(non_member_load, non_member_versioned_load, non_member_load_save);
CEREAL_MAKE_IS_SPECIALIZED(member_save_minimal, member_versioned_save_minimal, member_load_save_minimal);
CEREAL_MAKE_IS_SPECIALIZED(non_member_save_minimal, non_member_versioned_save_minimal, non_member_load_save_minimal);
CEREAL_MAKE_IS_SPECIALIZED(member_load_minimal, member_versioned_load_minimal, member_load_save_minimal);
CEREAL_MAKE_IS_SPECIALIZED(non_member_load_minimal, non_member_versioned_load_minimal, non_member_load_save_minimal);
#undef CEREAL_MAKE_IS_SPECIALIZED_ASSERT
#undef CEREAL_MAKE_IS_SPECIALIZED
// ######################################################################
// detects if a type has any active minimal output serialization
template <class T, class OutputArchive>
struct has_minimal_output_serialization : std::integral_constant<bool,
is_specialized_member_save_minimal<T, OutputArchive>::value ||
((has_member_save_minimal<T, OutputArchive>::value ||
has_non_member_save_minimal<T, OutputArchive>::value ||
has_member_versioned_save_minimal<T, OutputArchive>::value ||
has_non_member_versioned_save_minimal<T, OutputArchive>::value) &&
!(is_specialized_member_serialize<T, OutputArchive>::value ||
is_specialized_member_save<T, OutputArchive>::value))> {};
// ######################################################################
// detects if a type has any active minimal input serialization
template <class T, class InputArchive>
struct has_minimal_input_serialization : std::integral_constant<bool,
is_specialized_member_load_minimal<T, InputArchive>::value ||
((has_member_load_minimal<T, InputArchive>::value ||
has_non_member_load_minimal<T, InputArchive>::value ||
has_member_versioned_load_minimal<T, InputArchive>::value ||
has_non_member_versioned_load_minimal<T, InputArchive>::value) &&
!(is_specialized_member_serialize<T, InputArchive>::value ||
is_specialized_member_load<T, InputArchive>::value))> {};
// ######################################################################
namespace detail
{
template <class T, class OutputArchive>
struct count_output_serializers : std::integral_constant<int,
count_specializations<T, OutputArchive>::value ? count_specializations<T, OutputArchive>::value :
has_member_save<T, OutputArchive>::value +
has_non_member_save<T, OutputArchive>::value +
has_member_serialize<T, OutputArchive>::value +
has_non_member_serialize<T, OutputArchive>::value +
has_member_save_minimal<T, OutputArchive>::value +
has_non_member_save_minimal<T, OutputArchive>::value +
/*-versioned---------------------------------------------------------*/
has_member_versioned_save<T, OutputArchive>::value +
has_non_member_versioned_save<T, OutputArchive>::value +
has_member_versioned_serialize<T, OutputArchive>::value +
has_non_member_versioned_serialize<T, OutputArchive>::value +
has_member_versioned_save_minimal<T, OutputArchive>::value +
has_non_member_versioned_save_minimal<T, OutputArchive>::value> {};
}
template <class T, class OutputArchive>
struct is_output_serializable : std::integral_constant<bool,
detail::count_output_serializers<T, OutputArchive>::value == 1> {};
// ######################################################################
namespace detail
{
template <class T, class InputArchive>
struct count_input_serializers : std::integral_constant<int,
count_specializations<T, InputArchive>::value ? count_specializations<T, InputArchive>::value :
has_member_load<T, InputArchive>::value +
has_non_member_load<T, InputArchive>::value +
has_member_serialize<T, InputArchive>::value +
has_non_member_serialize<T, InputArchive>::value +
has_member_load_minimal<T, InputArchive>::value +
has_non_member_load_minimal<T, InputArchive>::value +
/*-versioned---------------------------------------------------------*/
has_member_versioned_load<T, InputArchive>::value +
has_non_member_versioned_load<T, InputArchive>::value +
has_member_versioned_serialize<T, InputArchive>::value +
has_non_member_versioned_serialize<T, InputArchive>::value +
has_member_versioned_load_minimal<T, InputArchive>::value +
has_non_member_versioned_load_minimal<T, InputArchive>::value> {};
}
template <class T, class InputArchive>
struct is_input_serializable : std::integral_constant<bool,
detail::count_input_serializers<T, InputArchive>::value == 1> {};
// ######################################################################
// Base Class Support
namespace detail
{
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; } };
} // namespace detail
namespace detail
{
struct BaseCastBase {};
template <class>
struct get_base_class;
template <template<typename> class Cast, class Base>
struct get_base_class<Cast<Base>>
{
using type = Base;
};
template <class Cast, template<class, class> class Test, class Archive,
bool IsBaseCast = std::is_base_of<BaseCastBase, Cast>::value>
struct has_minimal_base_class_serialization_impl : Test<typename get_base_class<Cast>::type, Archive>
{ };
template <class Cast, template<class, class> class Test, class Archive>
struct has_minimal_base_class_serialization_impl<Cast,Test, Archive, false> : std::false_type
{ };
}
template <class Cast, template<class, class> class Test, class Archive>
struct has_minimal_base_class_serialization : detail::has_minimal_base_class_serialization_impl<Cast, Test, Archive>
{ };
// ######################################################################
namespace detail
{
struct shared_from_this_wrapper
{
template <class U>
static auto (check)( U const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() );
static auto (check)( ... ) -> decltype( std::false_type() );
template <class U>
static auto get( U const & t ) -> decltype( t.shared_from_this() );
};
}
template<class T>
struct has_shared_from_this : decltype((detail::shared_from_this_wrapper::check)(std::declval<T>()))
{ };
template <class T>
struct get_shared_from_this_base
{
private:
using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
public:
using type = typename std::decay<typename PtrType::element_type>::type;
};
// ######################################################################
template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
struct strip_minimal
{
using type = T;
};
template <class T>
struct strip_minimal<T, true>
{
using type = typename T::type;
};
// ######################################################################
template <class T>
struct is_default_constructible
{
#ifdef CEREAL_OLDER_GCC
template <class TT, class SFINAE = void>
struct test : no {};
template <class TT>
struct test<TT, typename detail::Void< decltype( cereal::access::construct<TT>() ) >::type> : yes {};
static const bool value = test<T>();
#else // NOT CEREAL_OLDER_GCC =========================================
template <class TT>
static auto test(int) -> decltype( cereal::access::construct<TT>(), yes());
template <class>
static no test(...);
static const bool value = std::is_same<decltype(test<T>(0)), yes>::value;
#endif // NOT CEREAL_OLDER_GCC
};
// ######################################################################
namespace detail
{
template <class A>
using decay_archive = typename std::decay<typename strip_minimal<A>::type>::type;
}
template <class ArchiveT, class CerealArchiveT>
struct is_same_archive : std::integral_constant<bool,
std::is_same<detail::decay_archive<ArchiveT>, CerealArchiveT>::value>
{ };
// ######################################################################
#define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \
typename std::enable_if<cereal::traits::is_same_archive<Archive, INTYPE>::value || cereal::traits::is_same_archive<Archive, OUTTYPE>::value, void>::type
struct TextArchive {};
template <class A>
struct is_text_archive : std::integral_constant<bool,
std::is_base_of<TextArchive, detail::decay_archive<A>>::value>
{ };
} // namespace traits
// ######################################################################
namespace detail
{
template <class T, class A,
bool Member = traits::has_member_load_and_construct<T, A>::value,
bool MemberVersioned = traits::has_member_versioned_load_and_construct<T, A>::value,
bool NonMember = traits::has_non_member_load_and_construct<T, A>::value,
bool NonMemberVersioned = traits::has_non_member_versioned_load_and_construct<T, A>::value>
struct Construct
{
static_assert( cereal::traits::detail::delay_static_assert<T>::value,
"cereal found more than one compatible load_and_construct function for the provided type and archive combination. \n\n "
"Types must either have a member load_and_construct function or a non-member specialization of LoadAndConstruct (you may not mix these). \n "
"In addition, you may not mix versioned with non-versioned load_and_construct functions. \n\n " );
static T * load_andor_construct( A & /*ar*/, construct<T> & /*construct*/ )
{ return nullptr; }
};
// no load and construct case
template <class T, class A>
struct Construct<T, A, false, false, false, false>
{
static_assert( ::cereal::traits::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 void load_and_construct(Archive & ar, cereal::construct<T> & construct) \n "
"{ \n "
" var a; \n "
" ar( a ) \n "
" construct( a ); \n "
"} \n\n" );
static T * load_andor_construct()
{ return ::cereal::access::construct<T>(); }
};
// member non-versioned
template <class T, class A>
struct Construct<T, A, true, false, false, false>
{
static void load_andor_construct( A & ar, construct<T> & construct )
{
access::load_and_construct<T>( ar, construct );
}
};
// member versioned
template <class T, class A>
struct Construct<T, A, false, true, false, false>
{
static void load_andor_construct( A & ar, construct<T> & construct )
{
const auto version = ar.template loadClassVersion<T>();
access::load_and_construct<T>( ar, construct, version );
}
};
// non-member non-versioned
template <class T, class A>
struct Construct<T, A, false, false, true, false>
{
static void load_andor_construct( A & ar, construct<T> & construct )
{
LoadAndConstruct<T>::load_and_construct( ar, construct );
}
};
// non-member versioned
template <class T, class A>
struct Construct<T, A, false, false, false, true>
{
static void load_andor_construct( A & ar, construct<T> & construct )
{
const auto version = ar.template loadClassVersion<T>();
LoadAndConstruct<T>::load_and_construct( ar, construct, version );
}
};
} // namespace detail
} // namespace cereal
#endif // CEREAL_DETAILS_TRAITS_HPP_
cereal::traits::detail::NoConvertRef::type
Source type
Used to get underlying type easily.
Definition: traits.hpp:638
CEREAL_MAKE_IS_SPECIALIZED_IMPL
#define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name)
Create a test for a cereal::specialization entry.
Definition: traits.hpp:987
cereal::traits::detail::NoConvertRef
A struct that prevents implicit conversion.
Definition: traits.hpp:636
CEREAL_MAKE_HAS_NON_MEMBER_TEST
#define CEREAL_MAKE_HAS_NON_MEMBER_TEST(test_name, func, versioned)
Creates a test for whether a non const non-member function exists.
Definition: traits.hpp:217
cereal::traits::detail::EnableIfHelper
Definition: traits.hpp:79
cereal::traits::detail::shared_from_this_wrapper
Definition: traits.hpp:1202
cereal::traits::strip_minimal
Extracts the true type from something possibly wrapped in a cereal NoConvert.
Definition: traits.hpp:1239
cereal::traits::detail::decay_archive
typename std::decay< typename strip_minimal< A >::type >::type decay_archive
Removes all qualifiers and minimal wrappers from an archive.
Definition: traits.hpp:1276
cereal::traits::detail::get_output_from_input
Definition: traits.hpp:154
DisableIf
typename detail::DisableIfHelper< Conditions... >::type DisableIf
Provides a way to disable a function if conditions are met.
Definition: traits.hpp:148
cereal::traits::detail::delay_static_assert
Used to delay a static_assert until template instantiation.
Definition: traits.hpp:57
cereal::construct
Used to construct types with no default constructor.
Definition: access.hpp:164
cereal::traits::detail::count_output_serializers
The number of output serialization functions available.
Definition: traits.hpp:1093
CEREAL_MAKE_IS_SPECIALIZED
#define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name)
Generates a test for specialization for versioned and unversioned functions.
Definition: traits.hpp:1037
CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL
#define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned)
Creates a test for whether a member save function exists.
Definition: traits.hpp:300
cereal::traits::detail::base_class_id_hash
Definition: traits.hpp:1161
cereal::traits::detail::meta_bool_and
Definition: traits.hpp:70
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(test_name)
Creates a test for whether a member save_minimal function exists.
Definition: traits.hpp:502
cereal::traits::detail::NoConvertBase
Used to help strip away conversion wrappers.
Definition: traits.hpp:610
cereal::traits::detail::meta_bool_or
Definition: traits.hpp:73
cereal::LoadAndConstruct
A class that allows cereal to load smart pointers to types that have no default constructor.
Definition: access.hpp:108
cereal::traits::is_minimal_type
Definition: traits.hpp:413
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned)
Creates a test for whether a member load_minimal function exists.
Definition: traits.hpp:692
CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST
#define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(test_name, versioned)
Creates a test for whether a non-member save_minimal function exists.
Definition: traits.hpp:541
cereal::traits::has_invalid_output_versioning
Definition: traits.hpp:965
access.hpp
Access control and default construction.
cereal::traits::has_invalid_input_versioning
Definition: traits.hpp:975
cereal::traits::detail::NoConvertConstRef::type
Source type
Used to get underlying type easily.
Definition: traits.hpp:620
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(test_name, versioned)
Creates helpers for minimal save functions.
Definition: traits.hpp:482
CEREAL_SERIALIZE_FUNCTION_NAME
#define CEREAL_SERIALIZE_FUNCTION_NAME
The serialization/deserialization function name to search for.
Definition: macros.hpp:78
cereal::traits::has_member_versioned_load_and_construct
Member load and construct check (versioned)
Definition: traits.hpp:903
CEREAL_SAVE_MINIMAL_FUNCTION_NAME
#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME
The serialization (save_minimal) function name to search for.
Definition: macros.hpp:106
cereal::traits::is_same_archive
Checks if the provided archive type is equal to some cereal archive type.
Definition: traits.hpp:1290
cereal::traits::has_member_save
Definition: traits.hpp:327
macros.hpp
Preprocessor macros that can customise the cereal library.
CEREAL_LOAD_FUNCTION_NAME
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:85
cereal::traits::detail::base_class_id
Definition: traits.hpp:1145
cereal::detail::Construct
Definition: traits.hpp:1338
cereal::traits::has_member_load_and_construct
Member load and construct check.
Definition: traits.hpp:898
cereal::traits::TextArchive
Type traits only struct used to mark an archive as human readable (text based)
Definition: traits.hpp:1321
cereal::traits::is_default_constructible
Determines whether the class T can be default constructed by cereal::access.
Definition: traits.hpp:1254
cereal::traits::detail::has_minimal_base_class_serialization_impl
Base class cast, behave as the test.
Definition: traits.hpp:1181
cereal::traits::is_text_archive
Checks if an archive is a text archive (human readable)
Definition: traits.hpp:1325
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_test_name, save_test_name, save_test_prefix, versioned)
Creates helpers for minimal load functions.
Definition: traits.hpp:731
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_test_name, load_test_prefix)
Creates a test for whether a member load_minimal function exists.
Definition: traits.hpp:764
cereal::traits::has_minimal_base_class_serialization
Checks to see if the base class used in a cast has a minimal serialization.
Definition: traits.hpp:1195
cereal::traits::is_output_serializable
Definition: traits.hpp:1111
cereal::traits::detail::BaseCastBase
Common base type for base class casting.
Definition: traits.hpp:1167
cereal::traits::has_member_versioned_save
Definition: traits.hpp:340
CEREAL_MAKE_HAS_MEMBER_TEST
#define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned)
Creates a test for whether a non const member function exists.
Definition: traits.hpp:196
cereal::traits::has_shared_from_this
Determine if T or any base class of T has inherited from std::enable_shared_from_this.
Definition: traits.hpp:1216
cereal::traits::detail::is_string
Definition: traits.hpp:405
cereal::traits::get_shared_from_this_base
Get the type of the base class of T which inherited from std::enable_shared_from_this.
Definition: traits.hpp:1221
cereal::traits::is_specialized
Check if any specialization exists for a type.
Definition: traits.hpp:1014
cereal::traits::detail::count_specializations
Number of specializations detected.
Definition: traits.hpp:1003
cereal::traits::detail::DisableIfHelper
Definition: traits.hpp:82
cereal::traits::detail::get_base_class
Definition: traits.hpp:1170
cereal::traits::detail::has_member_versioned_load_and_construct_impl
Definition: traits.hpp:891
EnableIf
typename detail::EnableIfHelper< Conditions... >::type EnableIf
Provides a way to enable a function if conditions are met.
Definition: traits.hpp:116
cereal::traits::has_minimal_input_serialization
Definition: traits.hpp:1078
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned)
Creates implementation details for whether a member save_minimal function exists.
Definition: traits.hpp:449
cereal::traits::detail::has_member_load_and_construct_impl
Definition: traits.hpp:886
cereal::traits::detail::get_input_from_output
Definition: traits.hpp:161
cereal::traits::detail::count_input_serializers
The number of input serialization functions available.
Definition: traits.hpp:1120
cereal::traits::has_minimal_output_serialization
Definition: traits.hpp:1066
cereal::traits::detail::NoConvertConstRef
A struct that prevents implicit conversion.
Definition: traits.hpp:618
cereal::traits::get_shared_from_this_base::type
typename std::decay< typename PtrType::element_type >::type type
The type of the base of T that inherited from std::enable_shared_from_this.
Definition: traits.hpp:1227
CEREAL_LOAD_MINIMAL_FUNCTION_NAME
#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME
The deserialization (load_minimal) function name to search for.
Definition: macros.hpp:99
CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST
#define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(test_name, versioned)
Creates a test for whether a non-member load_and_construct specialization exists.
Definition: traits.hpp:910
CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST
#define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned)
Creates a test for whether a non-member load_minimal function exists.
Definition: traits.hpp:818
CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST
#define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(test_name, versioned)
Creates a test for whether a non-member save function exists.
Definition: traits.hpp:358
cereal::traits::detail::AnyConvert
A type that can implicitly convert to anything else.
Definition: traits.hpp:654
cereal::traits::is_input_serializable
Definition: traits.hpp:1138
cereal::traits::has_load_and_construct
Non member load and construct check.
Definition: traits.hpp:939
cereal::traits::has_non_member_split
Definition: traits.hpp:959
CEREAL_MAKE_VERSIONED_TEST
#define CEREAL_MAKE_VERSIONED_TEST
Used to convert a MAKE_HAS_XXX macro into a versioned variant.
Definition: traits.hpp:178
cereal::traits::detail::sfinae
sfinae
Return type for SFINAE Enablers.
Definition: traits.hpp:66
cereal::traits::has_member_split
Definition: traits.hpp:953