30 #ifndef CEREAL_DETAILS_TRAITS_HPP_
31 #define CEREAL_DETAILS_TRAITS_HPP_
34 #if (__GNUC__ == 4 && __GNUC_MINOR__ <= 7)
35 #define CEREAL_OLDER_GCC
36 #endif // gcc 4.7 or earlier
39 #include <type_traits>
49 using yes = std::true_type;
50 using no = std::false_type;
61 #ifdef CEREAL_OLDER_GCC // when VS supports better SFINAE, we can use this as the default
62 template<
typename>
struct Void {
typedef void type; };
63 #endif // CEREAL_OLDER_GCC
70 template <
bool H,
bool ... T>
struct meta_bool_and : std::integral_constant<bool, H && meta_bool_and<T...>::value> {};
71 template <
bool B>
struct meta_bool_and<B> : std::integral_constant<bool, B> {};
73 template <
bool H,
bool ... T>
struct meta_bool_or : std::integral_constant<bool, H || meta_bool_or<T...>::value> {};
74 template <
bool B>
struct meta_bool_or<B> : std::integral_constant<bool, B> {};
78 template <
bool ... Conditions>
79 struct EnableIfHelper : std::enable_if<meta_bool_and<Conditions...>::value, sfinae> {};
81 template <
bool ... Conditions>
82 struct DisableIfHelper : std::enable_if<!meta_bool_or<Conditions...>::value, sfinae> {};
115 template <
bool ... Conditions>
116 using EnableIf =
typename detail::EnableIfHelper<Conditions...>::type;
147 template <
bool ... Conditions>
148 using DisableIf =
typename detail::DisableIfHelper<Conditions...>::type;
153 template <
class InputArchive>
157 "Could not find an associated output archive for input archive." );
160 template <
class OutputArchive>
164 "Could not find an associated input archive for output archive." );
169 #define CEREAL_SETUP_ARCHIVE_TRAITS(InputArchive, OutputArchive) \
170 namespace cereal { namespace traits { namespace detail { \
171 template <> struct get_output_from_input<InputArchive> \
172 { using type = OutputArchive; }; \
173 template <> struct get_input_from_output<OutputArchive> \
174 { using type = InputArchive; }; } } }
178 #define CEREAL_MAKE_VERSIONED_TEST ,0
188 #ifdef CEREAL_OLDER_GCC
189 #define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned) \
190 template <class T, class A, class SFINAE = void> \
191 struct has_member_##test_name : no {}; \
192 template <class T, class A> \
193 struct has_member_##test_name<T, A, \
194 typename detail::Void< decltype( cereal::access::member_##name( std::declval<A&>(), std::declval<T&>() versioned ) ) >::type> : yes {}
195 #else // NOT CEREAL_OLDER_GCC
196 #define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned) \
199 template <class T, class A> \
200 struct has_member_##name##_##versioned##_impl \
202 template <class TT, class AA> \
203 static auto test(int) -> decltype( cereal::access::member_##name( std::declval<AA&>(), std::declval<TT&>() versioned ), yes()); \
204 template <class, class> \
205 static no test(...); \
206 static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
209 template <class T, class A> \
210 struct has_member_##test_name : std::integral_constant<bool, detail::has_member_##name##_##versioned##_impl<T, A>::value> {}
211 #endif // NOT CEREAL_OLDER_GCC
217 #define CEREAL_MAKE_HAS_NON_MEMBER_TEST(test_name, func, versioned) \
220 template <class T, class A> \
221 struct has_non_member_##test_name##_impl \
223 template <class TT, class AA> \
224 static auto test(int) -> decltype( func( std::declval<AA&>(), std::declval<TT&>() versioned ), yes()); \
225 template <class, class> \
226 static no test( ... ); \
227 static const bool value = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \
230 template <class T, class A> \
231 struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> {}
266 #undef CEREAL_MAKE_HAS_NON_MEMBER_TEST
267 #undef CEREAL_MAKE_HAS_MEMBER_TEST
276 #ifdef CEREAL_OLDER_GCC
277 #define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned) \
280 template <class T, class A> \
281 struct has_member_##test_name##_impl \
283 template <class TT, class AA, class SFINAE = void> struct test : no {}; \
284 template <class TT, class AA> \
285 struct test<TT, AA, \
286 typename detail::Void< decltype( cereal::access::member_save( std::declval<AA&>(), \
287 std::declval<TT const &>() versioned ) ) >::type> : yes {}; \
288 static const bool value = test<T, A>(); \
290 template <class TT, class AA, class SFINAE = void> struct test2 : no {}; \
291 template <class TT, class AA> \
292 struct test2<TT, AA, \
293 typename detail::Void< decltype( cereal::access::member_save_non_const( \
294 std::declval<AA&>(), \
295 std::declval<typename std::remove_const<TT>::type&>() versioned ) ) >::type> : yes {}; \
296 static const bool not_const_type = test2<T, A>(); \
300 #define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned) \
303 template <class T, class A> \
304 struct has_member_##test_name##_impl \
306 template <class TT, class AA> \
307 static auto test(int) -> decltype( cereal::access::member_save( std::declval<AA&>(), \
308 std::declval<TT const &>() versioned ), yes()); \
309 template <class, class> static no test(...); \
310 static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
312 template <class TT, class AA> \
313 static auto test2(int) -> decltype( cereal::access::member_save_non_const( \
314 std::declval<AA &>(), \
315 std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \
316 template <class, class> static no test2(...); \
317 static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \
326 template <class T, class A>
327 struct
has_member_save : std::integral_constant<
bool, detail::has_member_save_impl<T, A>::value>
329 typedef typename detail::has_member_save_impl<T, A> check;
330 static_assert( check::value || !check::not_const_type,
331 "cereal detected a non-const save. \n "
332 "save member functions must always be const" );
339 template <
class T,
class A>
342 typedef typename detail::has_member_versioned_save_impl<T, A> check;
343 static_assert( check::value || !check::not_const_type,
344 "cereal detected a versioned non-const save. \n "
345 "save member functions must always be const" );
349 #undef CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL
358 #define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(test_name, versioned) \
361 template <class T, class A> \
362 struct has_non_member_##test_name##_impl \
364 template <class TT, class AA> \
365 static auto test(int) -> decltype( CEREAL_SAVE_FUNCTION_NAME( \
366 std::declval<AA&>(), \
367 std::declval<TT const &>() versioned ), yes()); \
368 template <class, class> static no test(...); \
369 static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
371 template <class TT, class AA> \
372 static auto test2(int) -> decltype( CEREAL_SAVE_FUNCTION_NAME( \
373 std::declval<AA &>(), \
374 std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \
375 template <class, class> static no test2(...); \
376 static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \
380 template <class T, class A> \
381 struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> \
383 using check = typename detail::has_non_member_##test_name##_impl<T, A>; \
384 static_assert( check::value || !check::not_const_type, \
385 "cereal detected a non-const type parameter in non-member " #test_name ". \n " \
386 #test_name " non-member functions must always pass their types as const" ); \
398 #undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST
407 template <
class CharT,
class Traits,
class Alloc>
408 struct is_string<std::basic_string<CharT, Traits, Alloc>> : std::true_type {};
414 detail::is_string<T>::value || std::is_arithmetic<T>::value> {};
423 #ifdef CEREAL_OLDER_GCC
424 #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned) \
427 template <class T, class A> \
428 struct has_member_##test_name##_impl \
430 template <class TT, class AA, class SFINAE = void> struct test : no {}; \
431 template <class TT, class AA> \
432 struct test<TT, AA, typename detail::Void< decltype( \
433 cereal::access::member_save_minimal( std::declval<AA const &>(), \
434 std::declval<TT const &>() versioned ) ) >::type> : yes {}; \
436 static const bool value = test<T, A>(); \
438 template <class TT, class AA, class SFINAE = void> struct test2 : no {}; \
439 template <class TT, class AA> \
440 struct test2<TT, AA, typename detail::Void< decltype( \
441 cereal::access::member_save_minimal_non_const( std::declval<AA const &>(), \
442 std::declval<typename std::remove_const<TT>::type&>() versioned ) ) >::type> : yes {}; \
443 static const bool not_const_type = test2<T, A>(); \
445 static const bool valid = value || !not_const_type; \
449 #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned) \
452 template <class T, class A> \
453 struct has_member_##test_name##_impl \
455 template <class TT, class AA> \
456 static auto test(int) -> decltype( cereal::access::member_save_minimal( \
457 std::declval<AA const &>(), \
458 std::declval<TT const &>() versioned ), yes()); \
459 template <class, class> static no test(...); \
460 static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
462 template <class TT, class AA> \
463 static auto test2(int) -> decltype( cereal::access::member_save_minimal_non_const( \
464 std::declval<AA const &>(), \
465 std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \
466 template <class, class> static no test2(...); \
467 static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \
469 static const bool valid = value || !not_const_type; \
472 #endif // NOT CEREAL_OLDER_GCC
482 #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(test_name, versioned) \
485 template <class T, class A, bool Valid> \
486 struct get_member_##test_name##_type { using type = void; }; \
488 template <class T, class A> \
489 struct get_member_##test_name##_type<T, A, true> \
491 using type = decltype( cereal::access::member_save_minimal( std::declval<A const &>(), \
492 std::declval<T const &>() versioned ) ); \
502 #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(test_name) \
503 template <class T, class A> \
504 struct has_member_##test_name : std::integral_constant<bool, detail::has_member_##test_name##_impl<T, A>::value> \
506 using check = typename detail::has_member_##test_name##_impl<T, A>; \
507 static_assert( check::valid, \
508 "cereal detected a non-const member " #test_name ". \n " \
509 #test_name " member functions must always be const" ); \
511 using type = typename detail::get_member_##test_name##_type<T, A, check::value>::type; \
512 static_assert( (check::value && is_minimal_type<type>::value) || !check::value, \
513 "cereal detected a member " #test_name " with an invalid return type. \n " \
514 "return type must be arithmetic or string" ); \
530 #undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL
531 #undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL
532 #undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST
541 #define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(test_name, versioned) \
544 template <class T, class A> \
545 struct has_non_member_##test_name##_impl \
547 template <class TT, class AA> \
548 static auto test(int) -> decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( \
549 std::declval<AA const &>(), \
550 std::declval<TT const &>() versioned ), yes()); \
551 template <class, class> static no test(...); \
552 static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
554 template <class TT, class AA> \
555 static auto test2(int) -> decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( \
556 std::declval<AA const &>(), \
557 std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \
558 template <class, class> static no test2(...); \
559 static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \
561 static const bool valid = value || !not_const_type; \
564 template <class T, class A, bool Valid> \
565 struct get_non_member_##test_name##_type { using type = void; }; \
567 template <class T, class A> \
568 struct get_non_member_##test_name##_type <T, A, true> \
570 using type = decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( std::declval<A const &>(), \
571 std::declval<T const &>() versioned ) ); \
575 template <class T, class A> \
576 struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> \
578 using check = typename detail::has_non_member_##test_name##_impl<T, A>; \
579 static_assert( check::valid, \
580 "cereal detected a non-const type parameter in non-member " #test_name ". \n " \
581 #test_name " non-member functions must always pass their types as const" ); \
583 using type = typename detail::get_non_member_##test_name##_type<T, A, check::value>::type; \
584 static_assert( (check::value && is_minimal_type<type>::value) || !check::value, \
585 "cereal detected a non-member " #test_name " with an invalid return type. \n " \
586 "return type must be arithmetic or string" ); \
598 #undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST
617 template <
class Source>
622 template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>
::type>
623 operator Dest () =
delete;
626 template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>
::type>
627 operator Dest
const & ();
635 template <
class Source>
640 template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>
::type>
641 operator Dest () =
delete;
644 template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>
::type>
645 operator Dest
const & () =
delete;
649 template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>
::type>
656 template <
class Dest>
659 template <
class Dest>
660 operator Dest
const & ()
const;
675 #ifdef CEREAL_OLDER_GCC
676 #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned) \
679 template <class T, class A, class SFINAE = void> struct has_member_##test_name##_impl : no {}; \
680 template <class T, class A> \
681 struct has_member_##test_name##_impl<T, A, typename detail::Void< decltype( \
682 cereal::access::member_load_minimal( std::declval<A const &>(), \
683 std::declval<T &>(), AnyConvert() versioned ) ) >::type> : yes {}; \
685 template <class T, class A, class U, class SFINAE = void> struct has_member_##test_name##_type_impl : no {}; \
686 template <class T, class A, class U> \
687 struct has_member_##test_name##_type_impl<T, A, U, typename detail::Void< decltype( \
688 cereal::access::member_load_minimal( std::declval<A const &>(), \
689 std::declval<T &>(), NoConvertConstRef<U>() versioned ) ) >::type> : yes {}; \
692 #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned) \
695 template <class T, class A> \
696 struct has_member_##test_name##_impl \
698 template <class TT, class AA> \
699 static auto test(int) -> decltype( cereal::access::member_load_minimal( \
700 std::declval<AA const &>(), \
701 std::declval<TT &>(), AnyConvert() versioned ), yes()); \
702 template <class, class> static no test(...); \
703 static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \
705 template <class T, class A, class U> \
706 struct has_member_##test_name##_type_impl \
708 template <class TT, class AA, class UU> \
709 static auto test(int) -> decltype( cereal::access::member_load_minimal( \
710 std::declval<AA const &>(), \
711 std::declval<TT &>(), NoConvertConstRef<UU>() versioned ), yes()); \
712 template <class, class, class> static no test(...); \
713 static const bool value = std::is_same<decltype(test<T, A, U>(0)), yes>::value; \
717 #endif // NOT CEREAL_OLDER_GCC
731 #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_test_name, save_test_name, save_test_prefix, versioned) \
734 template <class T, class A, bool Valid> \
735 struct has_member_##load_test_name##_wrapper : std::false_type {}; \
737 template <class T, class A> \
738 struct has_member_##load_test_name##_wrapper<T, A, true> \
740 using AOut = typename detail::get_output_from_input<A>::type; \
742 static_assert( has_member_##save_test_prefix##_minimal<T, AOut>::value, \
743 "cereal detected member " #load_test_name " but no valid member " #save_test_name ". \n " \
744 "cannot evaluate correctness of " #load_test_name " without valid " #save_test_name "." ); \
746 using SaveType = typename detail::get_member_##save_test_prefix##_minimal_type<T, AOut, true>::type; \
747 const static bool value = has_member_##load_test_name##_impl<T, A>::value; \
748 const static bool valid = has_member_##load_test_name##_type_impl<T, A, SaveType>::value; \
750 static_assert( valid || !value, "cereal detected different or invalid types in corresponding member " \
751 #load_test_name " and " #save_test_name " functions. \n " \
752 "the paramater to " #load_test_name " must be a constant reference to the type that " \
753 #save_test_name " returns." ); \
764 #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_test_name, load_test_prefix) \
765 template <class T, class A> \
766 struct has_member_##load_test_prefix##_minimal : std::integral_constant<bool, \
767 detail::has_member_##load_test_name##_wrapper<T, A, detail::has_member_##load_test_name##_impl<T, A>::value>::value> {};
782 #undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL
783 #undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL
784 #undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST
790 #ifdef CEREAL_OLDER_GCC
793 #endif // CEREAL_OLDER_GCC
818 #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned) \
821 template <class T, class A, class U = void> \
822 struct has_non_member_##test_name##_impl \
824 template <class TT, class AA> \
825 static auto test(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
826 std::declval<AA const &>(), std::declval<TT&>(), AnyConvert() versioned ), yes() ); \
827 template <class, class> static no test( ... ); \
828 static const bool exists = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \
830 template <class TT, class AA, class UU> \
831 static auto test2(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
832 std::declval<AA const &>(), std::declval<TT&>(), NoConvertConstRef<UU>() versioned ), yes() ); \
833 template <class, class, class> static no test2( ... ); \
834 static const bool valid = std::is_same<decltype( test2<T, A, U>( 0 ) ), yes>::value; \
836 template <class TT, class AA> \
837 static auto test3(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
838 std::declval<AA const &>(), NoConvertRef<TT>(), AnyConvert() versioned ), yes() ); \
839 template <class, class> static no test3( ... ); \
840 static const bool const_valid = std::is_same<decltype( test3<T, A>( 0 ) ), yes>::value; \
843 template <class T, class A, bool Valid> \
844 struct has_non_member_##test_name##_wrapper : std::false_type {}; \
846 template <class T, class A> \
847 struct has_non_member_##test_name##_wrapper<T, A, true> \
849 using AOut = typename detail::get_output_from_input<A>::type; \
851 static_assert( detail::has_non_member_##save_name##_impl<T, AOut>::valid, \
852 "cereal detected non-member " #test_name " but no valid non-member " #save_name ". \n " \
853 "cannot evaluate correctness of " #test_name " without valid " #save_name "." ); \
855 using SaveType = typename detail::get_non_member_##save_name##_type<T, AOut, true>::type; \
856 using check = has_non_member_##test_name##_impl<T, A, SaveType>; \
857 static const bool value = check::exists; \
859 static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member " \
860 #test_name " and " #save_name " functions. \n " \
861 "the paramater to " #test_name " must be a constant reference to the type that " #save_name " returns." ); \
865 template <class T, class A> \
866 struct has_non_member_##test_name : std::integral_constant<bool, \
867 detail::has_non_member_##test_name##_wrapper<T, A, detail::has_non_member_##test_name##_impl<T, A>::exists>::value> {};
878 #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST
885 template<
typename T,
typename A>
887 std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
890 template<
typename T,
typename A>
892 std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>(), 0 ) ), void>::value>
897 template<
typename T,
typename A>
902 template<
typename T,
typename A>
910 #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(test_name, versioned) \
913 template <class T, class A> \
914 struct has_non_member_##test_name##_impl \
916 template <class TT, class AA> \
917 static auto test(int) -> decltype( LoadAndConstruct<TT>::load_and_construct( \
918 std::declval<AA&>(), std::declval< ::cereal::construct<TT>&>() versioned ), yes()); \
919 template <class, class> \
920 static no test( ... ); \
921 static const bool value = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \
924 template <class T, class A> \
925 struct has_non_member_##test_name : \
926 std::integral_constant<bool, detail::has_non_member_##test_name##_impl<typename std::remove_const<T>::type, A>::value> {};
938 template<typename T, typename A>
945 #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST
949 #undef CEREAL_MAKE_VERSIONED_TEST
952 template <
class T,
class InputArchive,
class OutputArchive>
954 (has_member_load<T, InputArchive>::value && has_member_save<T, OutputArchive>::value) ||
955 (has_member_versioned_load<T, InputArchive>::value && has_member_versioned_save<T, OutputArchive>::value)> {};
958 template <
class T,
class InputArchive,
class OutputArchive>
960 (has_non_member_load<T, InputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
961 (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_versioned_save<T, OutputArchive>::value)> {};
964 template <
class T,
class OutputArchive>
966 (has_member_versioned_save<T, OutputArchive>::value && has_member_save<T, OutputArchive>::value) ||
967 (has_non_member_versioned_save<T, OutputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
968 (has_member_versioned_serialize<T, OutputArchive>::value && has_member_serialize<T, OutputArchive>::value) ||
969 (has_non_member_versioned_serialize<T, OutputArchive>::value && has_non_member_serialize<T, OutputArchive>::value) ||
970 (has_member_versioned_save_minimal<T, OutputArchive>::value && has_member_save_minimal<T, OutputArchive>::value) ||
971 (has_non_member_versioned_save_minimal<T, OutputArchive>::value && has_non_member_save_minimal<T, OutputArchive>::value)> {};
974 template <
class T,
class InputArchive>
976 (has_member_versioned_load<T, InputArchive>::value && has_member_load<T, InputArchive>::value) ||
977 (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_load<T, InputArchive>::value) ||
978 (has_member_versioned_serialize<T, InputArchive>::value && has_member_serialize<T, InputArchive>::value) ||
979 (has_non_member_versioned_serialize<T, InputArchive>::value && has_non_member_serialize<T, InputArchive>::value) ||
980 (has_member_versioned_load_minimal<T, InputArchive>::value && has_member_load_minimal<T, InputArchive>::value) ||
981 (has_non_member_versioned_load_minimal<T, InputArchive>::value && has_non_member_load_minimal<T, InputArchive>::value)> {};
987 #define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name) \
988 template <class T, class A> \
989 struct is_specialized_##name : std::integral_constant<bool, \
990 !std::is_base_of<std::false_type, specialize<A, T, specialization::name>>::value> {}
999 #undef CEREAL_MAKE_IS_SPECIALIZED_IMPL
1002 template <
class T,
class A>
1004 is_specialized_member_serialize<T, A>::value +
1005 is_specialized_member_load_save<T, A>::value +
1006 is_specialized_member_load_save_minimal<T, A>::value +
1007 is_specialized_non_member_serialize<T, A>::value +
1008 is_specialized_non_member_load_save<T, A>::value +
1009 is_specialized_non_member_load_save_minimal<T, A>::value> {};
1013 template <
class T,
class A>
1015 detail::is_specialized_member_serialize<T, A>::value ||
1016 detail::is_specialized_member_load_save<T, A>::value ||
1017 detail::is_specialized_member_load_save_minimal<T, A>::value ||
1018 detail::is_specialized_non_member_serialize<T, A>::value ||
1019 detail::is_specialized_non_member_load_save<T, A>::value ||
1020 detail::is_specialized_non_member_load_save_minimal<T, A>::value>
1028 #define CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, print_name, spec_name) \
1029 static_assert( (is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value && \
1030 (has_##name<T, A>::value || has_##versioned_name<T, A>::value)) \
1031 || !(is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value), \
1032 "cereal detected " #print_name " specialization but no " #print_name " serialize function" )
1037 #define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name) \
1038 template <class T, class A> \
1039 struct is_specialized_##name : std::integral_constant<bool, \
1040 is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \
1041 { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, name, spec_name); }; \
1042 template <class T, class A> \
1043 struct is_specialized_##versioned_name : std::integral_constant<bool, \
1044 is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \
1045 { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, versioned_name, spec_name); }
1060 #undef CEREAL_MAKE_IS_SPECIALIZED_ASSERT
1061 #undef CEREAL_MAKE_IS_SPECIALIZED
1065 template <
class T,
class OutputArchive>
1067 is_specialized_member_save_minimal<T, OutputArchive>::value ||
1068 ((has_member_save_minimal<T, OutputArchive>::value ||
1069 has_non_member_save_minimal<T, OutputArchive>::value ||
1070 has_member_versioned_save_minimal<T, OutputArchive>::value ||
1071 has_non_member_versioned_save_minimal<T, OutputArchive>::value) &&
1072 !(is_specialized_member_serialize<T, OutputArchive>::value ||
1073 is_specialized_member_save<T, OutputArchive>::value))> {};
1077 template <
class T,
class InputArchive>
1079 is_specialized_member_load_minimal<T, InputArchive>::value ||
1080 ((has_member_load_minimal<T, InputArchive>::value ||
1081 has_non_member_load_minimal<T, InputArchive>::value ||
1082 has_member_versioned_load_minimal<T, InputArchive>::value ||
1083 has_non_member_versioned_load_minimal<T, InputArchive>::value) &&
1084 !(is_specialized_member_serialize<T, InputArchive>::value ||
1085 is_specialized_member_load<T, InputArchive>::value))> {};
1092 template <
class T,
class OutputArchive>
1094 count_specializations<T, OutputArchive>::value ? count_specializations<T, OutputArchive>::value :
1095 has_member_save<T, OutputArchive>::value +
1096 has_non_member_save<T, OutputArchive>::value +
1097 has_member_serialize<T, OutputArchive>::value +
1098 has_non_member_serialize<T, OutputArchive>::value +
1099 has_member_save_minimal<T, OutputArchive>::value +
1100 has_non_member_save_minimal<T, OutputArchive>::value +
1102 has_member_versioned_save<T, OutputArchive>::value +
1103 has_non_member_versioned_save<T, OutputArchive>::value +
1104 has_member_versioned_serialize<T, OutputArchive>::value +
1105 has_non_member_versioned_serialize<T, OutputArchive>::value +
1106 has_member_versioned_save_minimal<T, OutputArchive>::value +
1107 has_non_member_versioned_save_minimal<T, OutputArchive>::value> {};
1110 template <
class T,
class OutputArchive>
1112 detail::count_output_serializers<T, OutputArchive>::value == 1> {};
1119 template <
class T,
class InputArchive>
1121 count_specializations<T, InputArchive>::value ? count_specializations<T, InputArchive>::value :
1122 has_member_load<T, InputArchive>::value +
1123 has_non_member_load<T, InputArchive>::value +
1124 has_member_serialize<T, InputArchive>::value +
1125 has_non_member_serialize<T, InputArchive>::value +
1126 has_member_load_minimal<T, InputArchive>::value +
1127 has_non_member_load_minimal<T, InputArchive>::value +
1129 has_member_versioned_load<T, InputArchive>::value +
1130 has_non_member_versioned_load<T, InputArchive>::value +
1131 has_member_versioned_serialize<T, InputArchive>::value +
1132 has_non_member_versioned_serialize<T, InputArchive>::value +
1133 has_member_versioned_load_minimal<T, InputArchive>::value +
1134 has_non_member_versioned_load_minimal<T, InputArchive>::value> {};
1137 template <
class T,
class InputArchive>
1139 detail::count_input_serializers<T, InputArchive>::value == 1> {};
1151 hash(std::hash<std::type_index>()(
typeid(T)) ^ (std::hash<void const *>()(t) << 1))
1155 {
return (type == other.type) && (ptr == other.ptr); }
1157 std::type_index type;
1172 template <
template<
typename>
class Cast,
class Base>
1179 template <
class Cast,
template<
class,
class>
class Test,
class Archive,
1180 bool IsBaseCast = std::is_base_of<BaseCastBase, Cast>::value>
1185 template <
class Cast,
template<
class,
class>
class Test,
class Archive>
1194 template <
class Cast,
template<
class,
class>
class Test,
class Archive>
1205 static auto (check)( U
const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() );
1207 static auto (check)( ... ) -> decltype( std::false_type() );
1210 static auto get( U
const & t ) -> decltype( t.shared_from_this() );
1224 using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
1227 using type =
typename std::decay<typename PtrType::element_type>::type;
1238 template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
1248 using type =
typename T::type;
1256 #ifdef CEREAL_OLDER_GCC
1257 template <
class TT,
class SFINAE =
void>
1258 struct test : no {};
1260 struct test<TT, typename detail::Void< decltype( cereal::access::construct<TT>() ) >::type> : yes {};
1261 static const bool value = test<T>();
1262 #else // NOT CEREAL_OLDER_GCC =========================================
1264 static auto test(
int) -> decltype( cereal::access::construct<TT>(), yes());
1266 static no test(...);
1267 static const bool value = std::is_same<decltype(test<T>(0)), yes>::value;
1268 #endif // NOT CEREAL_OLDER_GCC
1276 using decay_archive =
typename std::decay<typename strip_minimal<A>::type>::type;
1289 template <
class ArchiveT,
class CerealArchiveT>
1291 std::is_same<detail::decay_archive<ArchiveT>, CerealArchiveT>::value>
1315 #define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \
1316 typename std::enable_if<cereal::traits::is_same_archive<Archive, INTYPE>::value || cereal::traits::is_same_archive<Archive, OUTTYPE>::value, void>::type
1326 std::is_base_of<TextArchive, detail::decay_archive<A>>::value>
1333 template <
class T,
class A,
1336 bool NonMember = traits::has_non_member_load_and_construct<T, A>::value,
1337 bool NonMemberVersioned = traits::has_non_member_versioned_load_and_construct<T, A>::value>
1341 "cereal found more than one compatible load_and_construct function for the provided type and archive combination. \n\n "
1342 "Types must either have a member load_and_construct function or a non-member specialization of LoadAndConstruct (you may not mix these). \n "
1343 "In addition, you may not mix versioned with non-versioned load_and_construct functions. \n\n " );
1344 static T * load_andor_construct( A & ,
construct<T> & )
1349 template <
class T,
class A>
1353 "Trying to serialize a an object with no default constructor. \n\n "
1354 "Types must either be default constructible or define either a member or non member Construct function. \n "
1355 "Construct functions generally have the signature: \n\n "
1356 "template <class Archive> \n "
1357 "static void load_and_construct(Archive & ar, cereal::construct<T> & construct) \n "
1361 " construct( a ); \n "
1363 static T * load_andor_construct()
1364 { return ::cereal::access::construct<T>(); }
1368 template <
class T,
class A>
1373 access::load_and_construct<T>( ar,
construct );
1378 template <
class T,
class A>
1383 const auto version = ar.template loadClassVersion<T>();
1384 access::load_and_construct<T>( ar,
construct, version );
1389 template <
class T,
class A>
1399 template <
class T,
class A>
1404 const auto version = ar.template loadClassVersion<T>();
1411 #endif // CEREAL_DETAILS_TRAITS_HPP_