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> {};
88 static const detail::sfinae 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>
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
806 #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned) \
809 template <class T, class A, class U = void> \
810 struct has_non_member_##test_name##_impl \
812 template <class TT, class AA> \
813 static auto test(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
814 std::declval<AA const &>(), std::declval<TT&>(), AnyConvert() versioned ), yes() ); \
815 template <class, class> static no test( ... ); \
816 static const bool exists = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \
818 template <class TT, class AA, class UU> \
819 static auto test2(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
820 std::declval<AA const &>(), std::declval<TT&>(), NoConvertConstRef<UU>() versioned ), yes() ); \
821 template <class, class, class> static no test2( ... ); \
822 static const bool valid = std::is_same<decltype( test2<T, A, U>( 0 ) ), yes>::value; \
824 template <class TT, class AA> \
825 static auto test3(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
826 std::declval<AA const &>(), NoConvertRef<TT>(), AnyConvert() versioned ), yes() ); \
827 template <class, class> static no test3( ... ); \
828 static const bool const_valid = std::is_same<decltype( test3<T, A>( 0 ) ), yes>::value; \
831 template <class T, class A, bool Valid> \
832 struct has_non_member_##test_name##_wrapper : std::false_type {}; \
834 template <class T, class A> \
835 struct has_non_member_##test_name##_wrapper<T, A, true> \
837 using AOut = typename detail::get_output_from_input<A>::type; \
839 static_assert( detail::has_non_member_##save_name##_impl<T, AOut>::valid, \
840 "cereal detected non-member " #test_name " but no valid non-member " #save_name ". \n " \
841 "cannot evaluate correctness of " #test_name " without valid " #save_name "." ); \
843 using SaveType = typename detail::get_non_member_##save_name##_type<T, AOut, true>::type; \
844 using check = has_non_member_##test_name##_impl<T, A, SaveType>; \
845 static const bool value = check::exists; \
847 static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member " \
848 #test_name " and " #save_name " functions. \n " \
849 "the paramater to " #test_name " must be a constant reference to the type that " #save_name " returns." ); \
850 static_assert( check::const_valid || !check::exists, \
851 "cereal detected an invalid serialization type parameter in non-member " #test_name ". " \
852 #test_name " non-member functions must accept their serialization type by non-const reference" ); \
856 template <class T, class A> \
857 struct has_non_member_##test_name : std::integral_constant<bool, \
858 detail::has_non_member_##test_name##_wrapper<T, A, detail::has_non_member_##test_name##_impl<T, A>::exists>::value> {};
869 #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST
873 #undef CEREAL_MAKE_VERSIONED_TEST
876 template <
class T,
class InputArchive,
class OutputArchive>
878 (has_member_load<T, InputArchive>::value && has_member_save<T, OutputArchive>::value) ||
879 (has_member_versioned_load<T, InputArchive>::value && has_member_versioned_save<T, OutputArchive>::value)> {};
882 template <
class T,
class InputArchive,
class OutputArchive>
884 (has_non_member_load<T, InputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
885 (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_versioned_save<T, OutputArchive>::value)> {};
888 template <
class T,
class OutputArchive>
890 (has_member_versioned_save<T, OutputArchive>::value && has_member_save<T, OutputArchive>::value) ||
891 (has_non_member_versioned_save<T, OutputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
892 (has_member_versioned_serialize<T, OutputArchive>::value && has_member_serialize<T, OutputArchive>::value) ||
893 (has_non_member_versioned_serialize<T, OutputArchive>::value && has_non_member_serialize<T, OutputArchive>::value) ||
894 (has_member_versioned_save_minimal<T, OutputArchive>::value && has_member_save_minimal<T, OutputArchive>::value) ||
895 (has_non_member_versioned_save_minimal<T, OutputArchive>::value && has_non_member_save_minimal<T, OutputArchive>::value)> {};
898 template <
class T,
class InputArchive>
900 (has_member_versioned_load<T, InputArchive>::value && has_member_load<T, InputArchive>::value) ||
901 (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_load<T, InputArchive>::value) ||
902 (has_member_versioned_serialize<T, InputArchive>::value && has_member_serialize<T, InputArchive>::value) ||
903 (has_non_member_versioned_serialize<T, InputArchive>::value && has_non_member_serialize<T, InputArchive>::value) ||
904 (has_member_versioned_load_minimal<T, InputArchive>::value && has_member_load_minimal<T, InputArchive>::value) ||
905 (has_non_member_versioned_load_minimal<T, InputArchive>::value && has_non_member_load_minimal<T, InputArchive>::value)> {};
911 #define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name) \
912 template <class T, class A> \
913 struct is_specialized_##name : std::integral_constant<bool, \
914 !std::is_base_of<std::false_type, specialize<A, T, specialization::name>>::value> {}
923 #undef CEREAL_MAKE_IS_SPECIALIZED_IMPL
926 template <
class T,
class A>
928 is_specialized_member_serialize<T, A>::value +
929 is_specialized_member_load_save<T, A>::value +
930 is_specialized_member_load_save_minimal<T, A>::value +
931 is_specialized_non_member_serialize<T, A>::value +
932 is_specialized_non_member_load_save<T, A>::value +
933 is_specialized_non_member_load_save_minimal<T, A>::value> {};
937 template <
class T,
class A>
939 detail::is_specialized_member_serialize<T, A>::value ||
940 detail::is_specialized_member_load_save<T, A>::value ||
941 detail::is_specialized_member_load_save_minimal<T, A>::value ||
942 detail::is_specialized_non_member_serialize<T, A>::value ||
943 detail::is_specialized_non_member_load_save<T, A>::value ||
944 detail::is_specialized_non_member_load_save_minimal<T, A>::value>
952 #define CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, print_name, spec_name) \
953 static_assert( (is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value && \
954 (has_##name<T, A>::value || has_##versioned_name<T, A>::value)) \
955 || !(is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value), \
956 "cereal detected " #print_name " specialization but no " #print_name " serialize function" )
961 #define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name) \
962 template <class T, class A> \
963 struct is_specialized_##name : std::integral_constant<bool, \
964 is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \
965 { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, name, spec_name); }; \
966 template <class T, class A> \
967 struct is_specialized_##versioned_name : std::integral_constant<bool, \
968 is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \
969 { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, versioned_name, spec_name); }
984 #undef CEREAL_MAKE_IS_SPECIALIZED_ASSERT
985 #undef CEREAL_MAKE_IS_SPECIALIZED
989 template <
class T,
class OutputArchive>
991 is_specialized_member_save_minimal<T, OutputArchive>::value ||
992 ((has_member_save_minimal<T, OutputArchive>::value ||
993 has_non_member_save_minimal<T, OutputArchive>::value ||
994 has_member_versioned_save_minimal<T, OutputArchive>::value ||
995 has_non_member_versioned_save_minimal<T, OutputArchive>::value) &&
996 !(is_specialized_member_serialize<T, OutputArchive>::value ||
997 is_specialized_member_save<T, OutputArchive>::value))> {};
1001 template <
class T,
class InputArchive>
1003 is_specialized_member_load_minimal<T, InputArchive>::value ||
1004 ((has_member_load_minimal<T, InputArchive>::value ||
1005 has_non_member_load_minimal<T, InputArchive>::value ||
1006 has_member_versioned_load_minimal<T, InputArchive>::value ||
1007 has_non_member_versioned_load_minimal<T, InputArchive>::value) &&
1008 !(is_specialized_member_serialize<T, InputArchive>::value ||
1009 is_specialized_member_load<T, InputArchive>::value))> {};
1016 template <
class T,
class OutputArchive>
1018 count_specializations<T, OutputArchive>::value ? count_specializations<T, OutputArchive>::value :
1019 has_member_save<T, OutputArchive>::value +
1020 has_non_member_save<T, OutputArchive>::value +
1021 has_member_serialize<T, OutputArchive>::value +
1022 has_non_member_serialize<T, OutputArchive>::value +
1023 has_member_save_minimal<T, OutputArchive>::value +
1024 has_non_member_save_minimal<T, OutputArchive>::value +
1026 has_member_versioned_save<T, OutputArchive>::value +
1027 has_non_member_versioned_save<T, OutputArchive>::value +
1028 has_member_versioned_serialize<T, OutputArchive>::value +
1029 has_non_member_versioned_serialize<T, OutputArchive>::value +
1030 has_member_versioned_save_minimal<T, OutputArchive>::value +
1031 has_non_member_versioned_save_minimal<T, OutputArchive>::value> {};
1034 template <
class T,
class OutputArchive>
1036 detail::count_output_serializers<T, OutputArchive>::value == 1> {};
1043 template <
class T,
class InputArchive>
1045 count_specializations<T, InputArchive>::value ? count_specializations<T, InputArchive>::value :
1046 has_member_load<T, InputArchive>::value +
1047 has_non_member_load<T, InputArchive>::value +
1048 has_member_serialize<T, InputArchive>::value +
1049 has_non_member_serialize<T, InputArchive>::value +
1050 has_member_load_minimal<T, InputArchive>::value +
1051 has_non_member_load_minimal<T, InputArchive>::value +
1053 has_member_versioned_load<T, InputArchive>::value +
1054 has_non_member_versioned_load<T, InputArchive>::value +
1055 has_member_versioned_serialize<T, InputArchive>::value +
1056 has_non_member_versioned_serialize<T, InputArchive>::value +
1057 has_member_versioned_load_minimal<T, InputArchive>::value +
1058 has_non_member_versioned_load_minimal<T, InputArchive>::value> {};
1061 template <
class T,
class InputArchive>
1063 detail::count_input_serializers<T, InputArchive>::value == 1> {};
1075 hash(std::hash<std::type_index>()(
typeid(T)) ^ (std::hash<void const *>()(t) << 1))
1079 {
return (type == other.type) && (ptr == other.ptr); }
1081 std::type_index type;
1096 template <
template<
typename>
class Cast,
class Base>
1103 template <
class Cast,
template<
class,
class>
class Test,
class Archive,
1104 bool IsBaseCast = std::is_base_of<BaseCastBase, Cast>::value>
1109 template <
class Cast,
template<
class,
class>
class Test,
class Archive>
1118 template <
class Cast,
template<
class,
class>
class Test,
class Archive>
1129 static auto check( U
const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() );
1131 static auto check( ... ) -> decltype( std::false_type() );
1134 static auto get( U
const & t ) -> decltype( t.shared_from_this() );
1148 using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
1151 using type =
typename std::decay<typename PtrType::element_type>::type;
1162 template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
1172 using type =
typename T::type;
1177 template<
typename T,
typename A>
1179 std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
1184 template<
typename T,
typename A>
1186 std::is_same<decltype( LoadAndConstruct<T>::load_and_construct( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
1191 template<
typename T,
typename A>
1193 has_member_load_and_construct<T, A>::value || has_non_member_load_and_construct<T, A>::value>
1201 #ifdef CEREAL_OLDER_GCC
1202 template <
class TT,
class SFINAE =
void>
1203 struct test : no {};
1205 struct test<TT, typename detail::Void< decltype( cereal::access::construct<TT>() ) >::type> : yes {};
1206 static const bool value = test<T>();
1207 #else // NOT CEREAL_OLDER_GCC =========================================
1209 static auto test(
int) -> decltype( cereal::access::construct<TT>(), yes());
1211 static no test(...);
1212 static const bool value = std::is_same<decltype(test<T>(0)), yes>::value;
1213 #endif // NOT CEREAL_OLDER_GCC
1221 using decay_archive =
typename std::decay<typename strip_minimal<A>::type>::type;
1234 template <
class ArchiveT,
class CerealArchiveT>
1236 std::is_same<detail::decay_archive<ArchiveT>, CerealArchiveT>::value>
1260 #define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \
1261 typename std::enable_if<cereal::traits::is_same_archive<Archive, INTYPE>::value || cereal::traits::is_same_archive<Archive, OUTTYPE>::value, void>::type
1271 std::is_base_of<TextArchive, detail::decay_archive<A>>::value>
1282 "Cereal detected both member and non member load_and_construct functions!" );
1283 static T * load_andor_construct( A & ,
construct<T> & )
1287 template <
class T,
class A>
1291 "Trying to serialize a an object with no default constructor. \n\n "
1292 "Types must either be default constructible or define either a member or non member Construct function. \n "
1293 "Construct functions generally have the signature: \n\n "
1294 "template <class Archive> \n "
1295 "static void load_and_construct(Archive & ar, cereal::construct<T> & construct) \n "
1299 " construct( a ); \n "
1301 static T * load_andor_construct()
1302 { return ::cereal::access::construct<T>(); }
1305 template <
class T,
class A>
1310 access::load_and_construct<T>( ar, construct );
1314 template <
class T,
class A>
1325 #endif // CEREAL_DETAILS_TRAITS_HPP_
#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
Has either a member or non member allocate.
Definition: traits.hpp:1192
Definition: traits.hpp:79
Definition: traits.hpp:413
Definition: traits.hpp:82
Check if any specialization exists for a type.
Definition: traits.hpp:938
Determines whether the class T can be default constructed by cereal::access.
Definition: traits.hpp:1199
Extracts the true type from something possibly wrapped in a cereal NoConvert.
Definition: traits.hpp:1163
The number of output serialization functions available.
Definition: traits.hpp:1017
Common base type for base class casting.
Definition: traits.hpp:1091
Source type
Used to get underlying type easily.
Definition: traits.hpp:638
Used to delay a static_assert until template instantiation.
Definition: traits.hpp:57
typename detail::EnableIfHelper< Conditions...>::type EnableIf
Provides a way to enable a function if conditions are met.
Definition: traits.hpp:116
Checks to see if the base class used in a cast has a minimal serialization.
Definition: traits.hpp:1119
Used to construct types with no default constructor.
Definition: access.hpp:151
static std::false_type load_and_construct(...)
Called by cereal if no default constructor exists to load and construct data simultaneously.
Definition: access.hpp:95
Checks if the provided archive type is equal to some cereal archive type.
Definition: traits.hpp:1235
Type traits only struct used to mark an archive as human readable (text based)
Definition: traits.hpp:1266
#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
Definition: traits.hpp:340
#define CEREAL_SERIALIZE_FUNCTION_NAME
The serialization/deserialization function name to search for.
Definition: macros.hpp:51
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:1151
A struct that prevents implicit conversion.
Definition: traits.hpp:636
Source type
Used to get underlying type easily.
Definition: traits.hpp:620
#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME
The serialization (save_minimal) function name to search for.
Definition: macros.hpp:79
A struct that prevents implicit conversion.
Definition: traits.hpp:618
#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
Definition: traits.hpp:1085
Checks if an archive is a text archive (human readable)
Definition: traits.hpp:1270
#define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name)
Generates a test for specialization for versioned and unversioned functions.
Definition: traits.hpp:961
Definition: traits.hpp:889
#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
Definition: traits.hpp:877
Member load and construct check.
Definition: traits.hpp:1178
#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
Determine if T or any base class of T has inherited from std::enable_shared_from_this.
Definition: traits.hpp:1140
Get the type of the base class of T which inherited from std::enable_shared_from_this.
Definition: traits.hpp:1145
Definition: traits.hpp:990
Definition: access.hpp:39
#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:806
Access control, default construction, and serialization disambiguation.
Definition: traits.hpp:1035
#define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name)
Create a test for a cereal::specialization entry.
Definition: traits.hpp:911
Definition: traits.hpp:883
Preprocessor macros that can customise the cereal library.
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:58
#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME
The deserialization (load_minimal) function name to search for.
Definition: macros.hpp:72
Used to help strip away conversion wrappers.
Definition: traits.hpp:610
Number of specializations detected.
Definition: traits.hpp:927
A type that can implicitly convert to anything else.
Definition: traits.hpp:654
#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
#define CEREAL_MAKE_VERSIONED_TEST
Used to convert a MAKE_HAS_XXX macro into a versioned variant.
Definition: traits.hpp:178
Definition: traits.hpp:405
#define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned)
Creates a test for whether a member save function exists.
Definition: traits.hpp:300
#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
Definition: traits.hpp:1126
Base class cast, behave as the test.
Definition: traits.hpp:1105
#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
#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
Definition: traits.hpp:1279
Definition: traits.hpp:1094
Non member load and construct check.
Definition: traits.hpp:1185
Definition: traits.hpp:1069
typename detail::DisableIfHelper< Conditions...>::type DisableIf
Provides a way to disable a function if conditions are met.
Definition: traits.hpp:148
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(test_name, versioned)
Creates helpers for minimal save functions.
Definition: traits.hpp:482
Definition: traits.hpp:327