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>
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 template<
typename T,
typename A>
875 std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
880 template<
typename T,
typename A>
882 std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>(), 0 ) ), void>::value>
889 #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(test_name, versioned) \ 892 template <class T, class A> \ 893 struct has_non_member_##test_name##_impl \ 895 template <class TT, class AA> \ 896 static auto test(int) -> decltype( LoadAndConstruct<TT>::load_and_construct( \ 897 std::declval<AA&>(), std::declval< ::cereal::construct<TT>&>() versioned ), yes()); \ 898 template <class, class> \ 899 static no test( ... ); \ 900 static const bool value = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \ 903 template <class T, class A> \ 904 struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> {}; 916 template<typename T, typename A>
923 #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST 927 #undef CEREAL_MAKE_VERSIONED_TEST 930 template <
class T,
class InputArchive,
class OutputArchive>
932 (has_member_load<T, InputArchive>::value && has_member_save<T, OutputArchive>::value) ||
933 (has_member_versioned_load<T, InputArchive>::value && has_member_versioned_save<T, OutputArchive>::value)> {};
936 template <
class T,
class InputArchive,
class OutputArchive>
938 (has_non_member_load<T, InputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
939 (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_versioned_save<T, OutputArchive>::value)> {};
942 template <
class T,
class OutputArchive>
944 (has_member_versioned_save<T, OutputArchive>::value && has_member_save<T, OutputArchive>::value) ||
945 (has_non_member_versioned_save<T, OutputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
946 (has_member_versioned_serialize<T, OutputArchive>::value && has_member_serialize<T, OutputArchive>::value) ||
947 (has_non_member_versioned_serialize<T, OutputArchive>::value && has_non_member_serialize<T, OutputArchive>::value) ||
948 (has_member_versioned_save_minimal<T, OutputArchive>::value && has_member_save_minimal<T, OutputArchive>::value) ||
949 (has_non_member_versioned_save_minimal<T, OutputArchive>::value && has_non_member_save_minimal<T, OutputArchive>::value)> {};
952 template <
class T,
class InputArchive>
954 (has_member_versioned_load<T, InputArchive>::value && has_member_load<T, InputArchive>::value) ||
955 (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_load<T, InputArchive>::value) ||
956 (has_member_versioned_serialize<T, InputArchive>::value && has_member_serialize<T, InputArchive>::value) ||
957 (has_non_member_versioned_serialize<T, InputArchive>::value && has_non_member_serialize<T, InputArchive>::value) ||
958 (has_member_versioned_load_minimal<T, InputArchive>::value && has_member_load_minimal<T, InputArchive>::value) ||
959 (has_non_member_versioned_load_minimal<T, InputArchive>::value && has_non_member_load_minimal<T, InputArchive>::value)> {};
965 #define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name) \ 966 template <class T, class A> \ 967 struct is_specialized_##name : std::integral_constant<bool, \ 968 !std::is_base_of<std::false_type, specialize<A, T, specialization::name>>::value> {} 977 #undef CEREAL_MAKE_IS_SPECIALIZED_IMPL 980 template <
class T,
class A>
982 is_specialized_member_serialize<T, A>::value +
983 is_specialized_member_load_save<T, A>::value +
984 is_specialized_member_load_save_minimal<T, A>::value +
985 is_specialized_non_member_serialize<T, A>::value +
986 is_specialized_non_member_load_save<T, A>::value +
987 is_specialized_non_member_load_save_minimal<T, A>::value> {};
991 template <
class T,
class A>
993 detail::is_specialized_member_serialize<T, A>::value ||
994 detail::is_specialized_member_load_save<T, A>::value ||
995 detail::is_specialized_member_load_save_minimal<T, A>::value ||
996 detail::is_specialized_non_member_serialize<T, A>::value ||
997 detail::is_specialized_non_member_load_save<T, A>::value ||
998 detail::is_specialized_non_member_load_save_minimal<T, A>::value>
1006 #define CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, print_name, spec_name) \ 1007 static_assert( (is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value && \ 1008 (has_##name<T, A>::value || has_##versioned_name<T, A>::value)) \ 1009 || !(is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value), \ 1010 "cereal detected " #print_name " specialization but no " #print_name " serialize function" ) 1015 #define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name) \ 1016 template <class T, class A> \ 1017 struct is_specialized_##name : std::integral_constant<bool, \ 1018 is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \ 1019 { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, name, spec_name); }; \ 1020 template <class T, class A> \ 1021 struct is_specialized_##versioned_name : std::integral_constant<bool, \ 1022 is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \ 1023 { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, versioned_name, spec_name); } 1038 #undef CEREAL_MAKE_IS_SPECIALIZED_ASSERT 1039 #undef CEREAL_MAKE_IS_SPECIALIZED 1043 template <
class T,
class OutputArchive>
1045 is_specialized_member_save_minimal<T, OutputArchive>::value ||
1046 ((has_member_save_minimal<T, OutputArchive>::value ||
1047 has_non_member_save_minimal<T, OutputArchive>::value ||
1048 has_member_versioned_save_minimal<T, OutputArchive>::value ||
1049 has_non_member_versioned_save_minimal<T, OutputArchive>::value) &&
1050 !(is_specialized_member_serialize<T, OutputArchive>::value ||
1051 is_specialized_member_save<T, OutputArchive>::value))> {};
1055 template <
class T,
class InputArchive>
1057 is_specialized_member_load_minimal<T, InputArchive>::value ||
1058 ((has_member_load_minimal<T, InputArchive>::value ||
1059 has_non_member_load_minimal<T, InputArchive>::value ||
1060 has_member_versioned_load_minimal<T, InputArchive>::value ||
1061 has_non_member_versioned_load_minimal<T, InputArchive>::value) &&
1062 !(is_specialized_member_serialize<T, InputArchive>::value ||
1063 is_specialized_member_load<T, InputArchive>::value))> {};
1070 template <
class T,
class OutputArchive>
1072 count_specializations<T, OutputArchive>::value ? count_specializations<T, OutputArchive>::value :
1073 has_member_save<T, OutputArchive>::value +
1074 has_non_member_save<T, OutputArchive>::value +
1075 has_member_serialize<T, OutputArchive>::value +
1076 has_non_member_serialize<T, OutputArchive>::value +
1077 has_member_save_minimal<T, OutputArchive>::value +
1078 has_non_member_save_minimal<T, OutputArchive>::value +
1080 has_member_versioned_save<T, OutputArchive>::value +
1081 has_non_member_versioned_save<T, OutputArchive>::value +
1082 has_member_versioned_serialize<T, OutputArchive>::value +
1083 has_non_member_versioned_serialize<T, OutputArchive>::value +
1084 has_member_versioned_save_minimal<T, OutputArchive>::value +
1085 has_non_member_versioned_save_minimal<T, OutputArchive>::value> {};
1088 template <
class T,
class OutputArchive>
1090 detail::count_output_serializers<T, OutputArchive>::value == 1> {};
1097 template <
class T,
class InputArchive>
1099 count_specializations<T, InputArchive>::value ? count_specializations<T, InputArchive>::value :
1100 has_member_load<T, InputArchive>::value +
1101 has_non_member_load<T, InputArchive>::value +
1102 has_member_serialize<T, InputArchive>::value +
1103 has_non_member_serialize<T, InputArchive>::value +
1104 has_member_load_minimal<T, InputArchive>::value +
1105 has_non_member_load_minimal<T, InputArchive>::value +
1107 has_member_versioned_load<T, InputArchive>::value +
1108 has_non_member_versioned_load<T, InputArchive>::value +
1109 has_member_versioned_serialize<T, InputArchive>::value +
1110 has_non_member_versioned_serialize<T, InputArchive>::value +
1111 has_member_versioned_load_minimal<T, InputArchive>::value +
1112 has_non_member_versioned_load_minimal<T, InputArchive>::value> {};
1115 template <
class T,
class InputArchive>
1117 detail::count_input_serializers<T, InputArchive>::value == 1> {};
1129 hash(std::hash<std::type_index>()(
typeid(T)) ^ (std::hash<void const *>()(t) << 1))
1133 {
return (type == other.type) && (ptr == other.ptr); }
1135 std::type_index type;
1150 template <
template<
typename>
class Cast,
class Base>
1157 template <
class Cast,
template<
class,
class>
class Test,
class Archive,
1158 bool IsBaseCast = std::is_base_of<BaseCastBase, Cast>::value>
1163 template <
class Cast,
template<
class,
class>
class Test,
class Archive>
1172 template <
class Cast,
template<
class,
class>
class Test,
class Archive>
1183 static auto (check)( U
const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() );
1185 static auto (check)( ... ) -> decltype( std::false_type() );
1188 static auto get( U
const & t ) -> decltype( t.shared_from_this() );
1202 using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
1205 using type =
typename std::decay<typename PtrType::element_type>::type;
1216 template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
1226 using type =
typename T::type;
1234 #ifdef CEREAL_OLDER_GCC 1235 template <
class TT,
class SFINAE =
void>
1236 struct test : no {};
1238 struct test<TT, typename detail::Void< decltype( cereal::access::construct<TT>() ) >::type> : yes {};
1239 static const bool value = test<T>();
1240 #else // NOT CEREAL_OLDER_GCC ========================================= 1242 static auto test(
int) -> decltype( cereal::access::construct<TT>(), yes());
1244 static no test(...);
1245 static const bool value = std::is_same<decltype(test<T>(0)), yes>::value;
1246 #endif // NOT CEREAL_OLDER_GCC 1254 using decay_archive =
typename std::decay<typename strip_minimal<A>::type>::type;
1267 template <
class ArchiveT,
class CerealArchiveT>
1269 std::is_same<detail::decay_archive<ArchiveT>, CerealArchiveT>::value>
1293 #define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \ 1294 typename std::enable_if<cereal::traits::is_same_archive<Archive, INTYPE>::value || cereal::traits::is_same_archive<Archive, OUTTYPE>::value, void>::type 1304 std::is_base_of<TextArchive, detail::decay_archive<A>>::value>
1311 template <
class T,
class A,
1314 bool NonMember = traits::has_non_member_load_and_construct<T, A>::value,
1315 bool NonMemberVersioned = traits::has_non_member_versioned_load_and_construct<T, A>::value>
1319 "cereal found more than one compatible load_and_construct function for the provided type and archive combination. \n\n " 1320 "Types must either have a member load_and_construct function or a non-member specialization of LoadAndConstruct (you may not mix these). \n " 1321 "In addition, you may not mix versioned with non-versioned load_and_construct functions. \n\n " );
1322 static T * load_andor_construct( A & ,
construct<T> & )
1327 template <
class T,
class A>
1331 "Trying to serialize a an object with no default constructor. \n\n " 1332 "Types must either be default constructible or define either a member or non member Construct function. \n " 1333 "Construct functions generally have the signature: \n\n " 1334 "template <class Archive> \n " 1335 "static void load_and_construct(Archive & ar, cereal::construct<T> & construct) \n " 1339 " construct( a ); \n " 1341 static T * load_andor_construct()
1342 { return ::cereal::access::construct<T>(); }
1346 template <
class T,
class A>
1351 access::load_and_construct<T>( ar, construct );
1356 template <
class T,
class A>
1361 const auto version = ar.template loadClassVersion<T>();
1362 access::load_and_construct<T>( ar, construct, version );
1367 template <
class T,
class A>
1377 template <
class T,
class A>
1382 const auto version = ar.template loadClassVersion<T>();
1389 #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
Non member load and construct check.
Definition: traits.hpp:917
Definition: traits.hpp:79
Definition: traits.hpp:413
Definition: traits.hpp:82
Check if any specialization exists for a type.
Definition: traits.hpp:992
#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:889
Determines whether the class T can be default constructed by cereal::access.
Definition: traits.hpp:1232
Extracts the true type from something possibly wrapped in a cereal NoConvert.
Definition: traits.hpp:1217
The number of output serialization functions available.
Definition: traits.hpp:1071
Common base type for base class casting.
Definition: traits.hpp:1145
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:1173
Used to construct types with no default constructor.
Definition: access.hpp:162
Checks if the provided archive type is equal to some cereal archive type.
Definition: traits.hpp:1268
Type traits only struct used to mark an archive as human readable (text based)
Definition: traits.hpp:1299
#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:78
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:1205
A struct that prevents implicit conversion.
Definition: traits.hpp:636
Source type
Used to get underlying type easily.
Definition: traits.hpp:620
A class that allows cereal to load smart pointers to types that have no default constructor.
Definition: access.hpp:107
#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME
The serialization (save_minimal) function name to search for.
Definition: macros.hpp:106
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:1139
Checks if an archive is a text archive (human readable)
Definition: traits.hpp:1303
#define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name)
Generates a test for specialization for versioned and unversioned functions.
Definition: traits.hpp:1015
Definition: traits.hpp:943
Member load and construct check (versioned)
Definition: traits.hpp:881
#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:931
Member load and construct check.
Definition: traits.hpp:874
#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:1194
Get the type of the base class of T which inherited from std::enable_shared_from_this.
Definition: traits.hpp:1199
Definition: traits.hpp:1044
Definition: access.hpp:40
#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
typename std::decay< typename strip_minimal< A >::type >::type decay_archive
Removes all qualifiers and minimal wrappers from an archive.
Definition: traits.hpp:1254
Access control, default construction, and serialization disambiguation.
sfinae
Return type for SFINAE Enablers.
Definition: traits.hpp:66
Definition: traits.hpp:1089
#define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name)
Create a test for a cereal::specialization entry.
Definition: traits.hpp:965
Definition: traits.hpp:937
Preprocessor macros that can customise the cereal library.
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:85
#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME
The deserialization (load_minimal) function name to search for.
Definition: macros.hpp:99
Used to help strip away conversion wrappers.
Definition: traits.hpp:610
Number of specializations detected.
Definition: traits.hpp:981
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:1180
Base class cast, behave as the test.
Definition: traits.hpp:1159
#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:1316
Definition: traits.hpp:1148
Definition: traits.hpp:1123
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