cereal
A C++11 library for serialization
traits.hpp
Go to the documentation of this file.
1
4/*
5 Copyright (c) 2014, Randolph Voorhies, Shane Grant
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions are met:
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 * Neither the name of the copyright holder nor the
16 names of its contributors may be used to endorse or promote products
17 derived from this software without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
23 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*/
30#ifndef CEREAL_DETAILS_TRAITS_HPP_
31#define CEREAL_DETAILS_TRAITS_HPP_
32
33#ifndef __clang__
34#if (__GNUC__ == 4 && __GNUC_MINOR__ <= 7)
35#define CEREAL_OLDER_GCC
36#endif // gcc 4.7 or earlier
37#endif // __clang__
38
39#include <type_traits>
40#include <typeindex>
41
42#include "cereal/macros.hpp"
43#include "cereal/access.hpp"
44
45namespace cereal
46{
47 namespace traits
48 {
49 using yes = std::true_type;
50 using no = std::false_type;
51
52 namespace detail
53 {
54 // ######################################################################
56 template <class T>
57 struct delay_static_assert : std::false_type {};
58
59 // ######################################################################
60 // SFINAE Helpers
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
64
66 enum class sfinae {};
67
68 // ######################################################################
69 // Helper functionality for boolean integral constants and Enable/DisableIf
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> {};
72
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> {};
75
76 // workaround needed due to bug in MSVC 2013, see
77 // http://connect.microsoft.com/VisualStudio/feedback/details/800231/c-11-alias-template-issue
78 template <bool ... Conditions>
79 struct EnableIfHelper : std::enable_if<meta_bool_and<Conditions...>::value, sfinae> {};
80
81 template <bool ... Conditions>
82 struct DisableIfHelper : std::enable_if<!meta_bool_or<Conditions...>::value, sfinae> {};
83 } // namespace detail
84
86
88 static const detail::sfinae sfinae = {};
89
90 // ######################################################################
92
115 template <bool ... Conditions>
116 using EnableIf = typename detail::EnableIfHelper<Conditions...>::type;
117
118 // ######################################################################
120
147 template <bool ... Conditions>
148 using DisableIf = typename detail::DisableIfHelper<Conditions...>::type;
149
150 // ######################################################################
151 namespace detail
152 {
153 template <class InputArchive>
155 {
157 "Could not find an associated output archive for input archive." );
158 };
159
160 template <class OutputArchive>
162 {
164 "Could not find an associated input archive for output archive." );
165 };
166 }
167
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; }; } } } /* end namespaces */
175
176 // ######################################################################
178 #define CEREAL_MAKE_VERSIONED_TEST ,0
179
180 // ######################################################################
182
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) \
197 namespace detail \
198 { \
199 template <class T, class A> \
200 struct has_member_##name##_##versioned##_impl \
201 { \
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; \
207 }; \
208 } /* end namespace detail */ \
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
212
213 // ######################################################################
215
217 #define CEREAL_MAKE_HAS_NON_MEMBER_TEST(test_name, func, versioned) \
218 namespace detail \
219 { \
220 template <class T, class A> \
221 struct has_non_member_##test_name##_impl \
222 { \
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; \
228 }; \
229 } /* end namespace detail */ \
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> {}
232
233 // ######################################################################
234 // Member Serialize
235 CEREAL_MAKE_HAS_MEMBER_TEST(serialize, serialize,);
236
237 // ######################################################################
238 // Member Serialize (versioned)
239 CEREAL_MAKE_HAS_MEMBER_TEST(serialize, versioned_serialize, CEREAL_MAKE_VERSIONED_TEST);
240
241 // ######################################################################
242 // Non Member Serialize
244
245 // ######################################################################
246 // Non Member Serialize (versioned)
248
249 // ######################################################################
250 // Member Load
251 CEREAL_MAKE_HAS_MEMBER_TEST(load, load,);
252
253 // ######################################################################
254 // Member Load (versioned)
256
257 // ######################################################################
258 // Non Member Load
260
261 // ######################################################################
262 // Non Member Load (versioned)
264
265 // ######################################################################
266 #undef CEREAL_MAKE_HAS_NON_MEMBER_TEST
267 #undef CEREAL_MAKE_HAS_MEMBER_TEST
268
269 // ######################################################################
271
276 #ifdef CEREAL_OLDER_GCC
277 #define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned) \
278 namespace detail \
279 { \
280 template <class T, class A> \
281 struct has_member_##test_name##_impl \
282 { \
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>(); \
289 \
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>(); \
297 }; \
298 } /* end namespace detail */
299 #else /* NOT CEREAL_OLDER_GCC =================================== */
300 #define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned) \
301 namespace detail \
302 { \
303 template <class T, class A> \
304 struct has_member_##test_name##_impl \
305 { \
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; \
311 \
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; \
318 }; \
319 } /* end namespace detail */
320 #endif /* NOT CEREAL_OLDER_GCC */
321
322 // ######################################################################
323 // Member Save
325
326 template <class T, class A>
327 struct has_member_save : std::integral_constant<bool, detail::has_member_save_impl<T, A>::value>
328 {
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" );
333 };
334
335 // ######################################################################
336 // Member Save (versioned)
338
339 template <class T, class A>
340 struct has_member_versioned_save : std::integral_constant<bool, detail::has_member_versioned_save_impl<T, A>::value>
341 {
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" );
346 };
347
348 // ######################################################################
349 #undef CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL
350
351 // ######################################################################
353
358 #define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(test_name, versioned) \
359 namespace detail \
360 { \
361 template <class T, class A> \
362 struct has_non_member_##test_name##_impl \
363 { \
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; \
370 \
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; \
377 }; \
378 } /* end namespace detail */ \
379 \
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> \
382 { \
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" ); \
387 };
388
389 // ######################################################################
390 // Non Member Save
392
393 // ######################################################################
394 // Non Member Save (versioned)
396
397 // ######################################################################
398 #undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST
399
400 // ######################################################################
401 // Minimal Utilities
402 namespace detail
403 {
404 // Determines if the provided type is an std::string
405 template <class> struct is_string : std::false_type {};
406
407 template <class CharT, class Traits, class Alloc>
408 struct is_string<std::basic_string<CharT, Traits, Alloc>> : std::true_type {};
409 }
410
411 // Determines if the type is valid for use with a minimal serialize function
412 template <class T>
413 struct is_minimal_type : std::integral_constant<bool,
414 detail::is_string<T>::value || std::is_arithmetic<T>::value> {};
415
416 // ######################################################################
418
423 #ifdef CEREAL_OLDER_GCC
424 #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned) \
425 namespace detail \
426 { \
427 template <class T, class A> \
428 struct has_member_##test_name##_impl \
429 { \
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 {}; \
435 \
436 static const bool value = test<T, A>(); \
437 \
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>(); \
444 \
445 static const bool valid = value || !not_const_type; \
446 }; \
447 } /* end namespace detail */
448 #else /* NOT CEREAL_OLDER_GCC =================================== */
449 #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned) \
450 namespace detail \
451 { \
452 template <class T, class A> \
453 struct has_member_##test_name##_impl \
454 { \
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; \
461 \
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; \
468 \
469 static const bool valid = value || !not_const_type; \
470 }; \
471 } /* end namespace detail */
472 #endif // NOT CEREAL_OLDER_GCC
473
474 // ######################################################################
476
482 #define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(test_name, versioned) \
483 namespace detail \
484 { \
485 template <class T, class A, bool Valid> \
486 struct get_member_##test_name##_type { using type = void; }; \
487 \
488 template <class T, class A> \
489 struct get_member_##test_name##_type<T, A, true> \
490 { \
491 using type = decltype( cereal::access::member_save_minimal( std::declval<A const &>(), \
492 std::declval<T const &>() versioned ) ); \
493 }; \
494 } /* end namespace detail */
495
496 // ######################################################################
498
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> \
505 { \
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" ); \
510 \
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" ); \
515 };
516
517 // ######################################################################
518 // Member Save Minimal
522
523 // ######################################################################
524 // Member Save Minimal (versioned)
527 CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(versioned_save_minimal)
528
529 // ######################################################################
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
533
534 // ######################################################################
536
541 #define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(test_name, versioned) \
542 namespace detail \
543 { \
544 template <class T, class A> \
545 struct has_non_member_##test_name##_impl \
546 { \
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; \
553 \
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; \
560 \
561 static const bool valid = value || !not_const_type; \
562 }; \
563 \
564 template <class T, class A, bool Valid> \
565 struct get_non_member_##test_name##_type { using type = void; }; \
566 \
567 template <class T, class A> \
568 struct get_non_member_##test_name##_type <T, A, true> \
569 { \
570 using type = decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( std::declval<A const &>(), \
571 std::declval<T const &>() versioned ) ); \
572 }; \
573 } /* end namespace detail */ \
574 \
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> \
577 { \
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" ); \
582 \
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" ); \
587 };
588
589 // ######################################################################
590 // Non-Member Save Minimal
592
593 // ######################################################################
594 // Non-Member Save Minimal (versioned)
596
597 // ######################################################################
598 #undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST
599
600 // ######################################################################
601 // Load Minimal Utilities
602 namespace detail
603 {
605
610 struct NoConvertBase {};
611
613
617 template <class Source>
619 {
620 using type = Source;
621
622 template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
623 operator Dest () = delete;
624
626 template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
627 operator Dest const & ();
628 };
629
631
635 template <class Source>
637 {
638 using type = Source;
639
640 template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
641 operator Dest () = delete;
642
643 #ifdef __clang__
644 template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
645 operator Dest const & () = delete;
646 #endif // __clang__
647
649 template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
650 operator Dest & ();
651 };
652
655 {
656 template <class Dest>
657 operator Dest & ();
658
659 template <class Dest>
660 operator Dest const & () const;
661 };
662 } // namespace detail
663
664 // ######################################################################
666
675 #ifdef CEREAL_OLDER_GCC
676 #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned) \
677 namespace detail \
678 { \
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 {}; \
684 \
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 {}; \
690 } /* end namespace detail */
691 #else /* NOT CEREAL_OLDER_GCC =================================== */
692 #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned) \
693 namespace detail \
694 { \
695 template <class T, class A> \
696 struct has_member_##test_name##_impl \
697 { \
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; \
704 }; \
705 template <class T, class A, class U> \
706 struct has_member_##test_name##_type_impl \
707 { \
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; \
714 \
715 }; \
716 } /* end namespace detail */
717 #endif // NOT CEREAL_OLDER_GCC
718
719 // ######################################################################
721
731 #define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_test_name, save_test_name, save_test_prefix, versioned) \
732 namespace detail \
733 { \
734 template <class T, class A, bool Valid> \
735 struct has_member_##load_test_name##_wrapper : std::false_type {}; \
736 \
737 template <class T, class A> \
738 struct has_member_##load_test_name##_wrapper<T, A, true> \
739 { \
740 using AOut = typename detail::get_output_from_input<A>::type; \
741 \
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 "." ); \
745 \
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; \
749 \
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." ); \
754 }; \
755 } /* end namespace detail */
756
757 // ######################################################################
759
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> {};
768
769 // ######################################################################
770 // Member Load Minimal
772 CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_minimal, save_minimal, save, )
774
775 // ######################################################################
776 // Member Load Minimal (versioned)
778 CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(versioned_load_minimal, versioned_save_minimal, versioned_save, CEREAL_MAKE_VERSIONED_TEST)
779 CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_load)
780
781 // ######################################################################
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
785
786 // ######################################################################
787 // Non-Member Load Minimal
788 namespace detail
789 {
790 #ifdef CEREAL_OLDER_GCC
791 void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(); // prevents nonsense complaining about not finding this
793 #endif // CEREAL_OLDER_GCC
794 } // namespace detail
795
796 // ######################################################################
798
818 #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned) \
819 namespace detail \
820 { \
821 template <class T, class A, class U = void> \
822 struct has_non_member_##test_name##_impl \
823 { \
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; \
829 \
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; \
835 \
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; \
841 }; \
842 \
843 template <class T, class A, bool Valid> \
844 struct has_non_member_##test_name##_wrapper : std::false_type {}; \
845 \
846 template <class T, class A> \
847 struct has_non_member_##test_name##_wrapper<T, A, true> \
848 { \
849 using AOut = typename detail::get_output_from_input<A>::type; \
850 \
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 "." ); \
854 \
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; \
858 \
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." ); \
862 }; \
863 } /* namespace detail */ \
864 \
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> {};
868
869 // ######################################################################
870 // Non-Member Load Minimal
871 CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(load_minimal, save_minimal, )
872
873 // ######################################################################
874 // Non-Member Load Minimal (versioned)
875 CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
876
877 // ######################################################################
878 #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST
879
880 // ######################################################################
881 namespace detail
882 {
883 // const stripped away before reaching here, prevents errors on conversion from
884 // construct<const T> to construct<T>
885 template<typename T, typename A>
886 struct has_member_load_and_construct_impl : std::integral_constant<bool,
887 std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
888 { };
889
890 template<typename T, typename A>
891 struct has_member_versioned_load_and_construct_impl : std::integral_constant<bool,
892 std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>(), 0 ) ), void>::value>
893 { };
894 } // namespace detail
895
897 template<typename T, typename A>
898 struct has_member_load_and_construct : detail::has_member_load_and_construct_impl<typename std::remove_const<T>::type, A>
899 { };
900
902 template<typename T, typename A>
904 { };
905
906 // ######################################################################
908
910 #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(test_name, versioned) \
911 namespace detail \
912 { \
913 template <class T, class A> \
914 struct has_non_member_##test_name##_impl \
915 { \
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; \
922 }; \
923 } /* end namespace detail */ \
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> {};
927
928 // ######################################################################
931
932 // ######################################################################
935
936 // ######################################################################
938 template<typename T, typename A>
939 struct has_load_and_construct : std::integral_constant<bool,
940 has_member_load_and_construct<T, A>::value || has_non_member_load_and_construct<T, A>::value ||
941 has_member_versioned_load_and_construct<T, A>::value || has_non_member_versioned_load_and_construct<T, A>::value>
942 { };
943
944 // ######################################################################
945 #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST
946
947 // ######################################################################
948 // End of serialization existence tests
949 #undef CEREAL_MAKE_VERSIONED_TEST
950
951 // ######################################################################
952 template <class T, class InputArchive, class OutputArchive>
953 struct has_member_split : std::integral_constant<bool,
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)> {};
956
957 // ######################################################################
958 template <class T, class InputArchive, class OutputArchive>
959 struct has_non_member_split : std::integral_constant<bool,
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)> {};
962
963 // ######################################################################
964 template <class T, class OutputArchive>
965 struct has_invalid_output_versioning : std::integral_constant<bool,
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)> {};
972
973 // ######################################################################
974 template <class T, class InputArchive>
975 struct has_invalid_input_versioning : std::integral_constant<bool,
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)> {};
982
983 // ######################################################################
984 namespace detail
985 {
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> {}
991
992 CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_serialize);
993 CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save);
994 CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save_minimal);
995 CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_serialize);
996 CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save);
997 CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save_minimal);
998
999 #undef CEREAL_MAKE_IS_SPECIALIZED_IMPL
1000
1002 template <class T, class A>
1003 struct count_specializations : std::integral_constant<int,
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> {};
1010 } // namespace detail
1011
1013 template <class T, class A>
1014 struct is_specialized : std::integral_constant<bool,
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>
1021 {
1022 static_assert(detail::count_specializations<T, A>::value <= 1, "More than one explicit specialization detected for type.");
1023 };
1024
1026
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" )
1033
1035
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); }
1046
1047 CEREAL_MAKE_IS_SPECIALIZED(member_serialize, member_versioned_serialize, member_serialize);
1048 CEREAL_MAKE_IS_SPECIALIZED(non_member_serialize, non_member_versioned_serialize, non_member_serialize);
1049
1050 CEREAL_MAKE_IS_SPECIALIZED(member_save, member_versioned_save, member_load_save);
1051 CEREAL_MAKE_IS_SPECIALIZED(non_member_save, non_member_versioned_save, non_member_load_save);
1052 CEREAL_MAKE_IS_SPECIALIZED(member_load, member_versioned_load, member_load_save);
1053 CEREAL_MAKE_IS_SPECIALIZED(non_member_load, non_member_versioned_load, non_member_load_save);
1054
1055 CEREAL_MAKE_IS_SPECIALIZED(member_save_minimal, member_versioned_save_minimal, member_load_save_minimal);
1056 CEREAL_MAKE_IS_SPECIALIZED(non_member_save_minimal, non_member_versioned_save_minimal, non_member_load_save_minimal);
1057 CEREAL_MAKE_IS_SPECIALIZED(member_load_minimal, member_versioned_load_minimal, member_load_save_minimal);
1058 CEREAL_MAKE_IS_SPECIALIZED(non_member_load_minimal, non_member_versioned_load_minimal, non_member_load_save_minimal);
1059
1060 #undef CEREAL_MAKE_IS_SPECIALIZED_ASSERT
1061 #undef CEREAL_MAKE_IS_SPECIALIZED
1062
1063 // ######################################################################
1064 // detects if a type has any active minimal output serialization
1065 template <class T, class OutputArchive>
1066 struct has_minimal_output_serialization : std::integral_constant<bool,
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))> {};
1074
1075 // ######################################################################
1076 // detects if a type has any active minimal input serialization
1077 template <class T, class InputArchive>
1078 struct has_minimal_input_serialization : std::integral_constant<bool,
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))> {};
1086
1087 // ######################################################################
1088 namespace detail
1089 {
1091
1092 template <class T, class OutputArchive>
1093 struct count_output_serializers : std::integral_constant<int,
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 +
1101 /*-versioned---------------------------------------------------------*/
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> {};
1108 }
1109
1110 template <class T, class OutputArchive>
1111 struct is_output_serializable : std::integral_constant<bool,
1112 detail::count_output_serializers<T, OutputArchive>::value == 1> {};
1113
1114 // ######################################################################
1115 namespace detail
1116 {
1118
1119 template <class T, class InputArchive>
1120 struct count_input_serializers : std::integral_constant<int,
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 +
1128 /*-versioned---------------------------------------------------------*/
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> {};
1135 }
1136
1137 template <class T, class InputArchive>
1138 struct is_input_serializable : std::integral_constant<bool,
1139 detail::count_input_serializers<T, InputArchive>::value == 1> {};
1140
1141 // ######################################################################
1142 // Base Class Support
1143 namespace detail
1144 {
1146 {
1147 template<class T>
1148 base_class_id(T const * const t) :
1149 type(typeid(T)),
1150 ptr(t),
1151 hash(std::hash<std::type_index>()(typeid(T)) ^ (std::hash<void const *>()(t) << 1))
1152 { }
1153
1154 bool operator==(base_class_id const & other) const
1155 { return (type == other.type) && (ptr == other.ptr); }
1156
1157 std::type_index type;
1158 void const * ptr;
1159 size_t hash;
1160 };
1161 struct base_class_id_hash { size_t operator()(base_class_id const & id) const { return id.hash; } };
1162 } // namespace detail
1163
1164 namespace detail
1165 {
1167 struct BaseCastBase {};
1168
1169 template <class>
1171
1172 template <template<typename> class Cast, class Base>
1173 struct get_base_class<Cast<Base>>
1174 {
1175 using type = Base;
1176 };
1177
1179 template <class Cast, template<class, class> class Test, class Archive,
1180 bool IsBaseCast = std::is_base_of<BaseCastBase, Cast>::value>
1181 struct has_minimal_base_class_serialization_impl : Test<typename get_base_class<Cast>::type, Archive>
1182 { };
1183
1185 template <class Cast, template<class, class> class Test, class Archive>
1186 struct has_minimal_base_class_serialization_impl<Cast,Test, Archive, false> : std::false_type
1187 { };
1188 }
1189
1191
1194 template <class Cast, template<class, class> class Test, class Archive>
1196 { };
1197
1198
1199 // ######################################################################
1200 namespace detail
1201 {
1203 {
1204 template <class U>
1205 static auto (check)( U const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() );
1206
1207 static auto (check)( ... ) -> decltype( std::false_type() );
1208
1209 template <class U>
1210 static auto get( U const & t ) -> decltype( t.shared_from_this() );
1211 };
1212 }
1213
1215 template<class T>
1216 struct has_shared_from_this : decltype((detail::shared_from_this_wrapper::check)(std::declval<T>()))
1217 { };
1218
1220 template <class T>
1222 {
1223 private:
1224 using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
1225 public:
1227 using type = typename std::decay<typename PtrType::element_type>::type;
1228 };
1229
1230 // ######################################################################
1232
1238 template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
1240 {
1241 using type = T;
1242 };
1243
1245 template <class T>
1246 struct strip_minimal<T, true>
1247 {
1248 using type = typename T::type;
1249 };
1250
1251 // ######################################################################
1253 template <class T>
1255 {
1256 #ifdef CEREAL_OLDER_GCC
1257 template <class TT, class SFINAE = void>
1258 struct test : no {};
1259 template <class TT>
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 =========================================
1263 template <class TT>
1264 static auto test(int) -> decltype( cereal::access::construct<TT>(), yes());
1265 template <class>
1266 static no test(...);
1267 static const bool value = std::is_same<decltype(test<T>(0)), yes>::value;
1268 #endif // NOT CEREAL_OLDER_GCC
1269 };
1270
1271 // ######################################################################
1272 namespace detail
1273 {
1275 template <class A>
1276 using decay_archive = typename std::decay<typename strip_minimal<A>::type>::type;
1277 }
1278
1280
1289 template <class ArchiveT, class CerealArchiveT>
1290 struct is_same_archive : std::integral_constant<bool,
1291 std::is_same<detail::decay_archive<ArchiveT>, CerealArchiveT>::value>
1292 { };
1293
1294 // ######################################################################
1296
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
1317
1319
1321 struct TextArchive {};
1322
1324 template <class A>
1325 struct is_text_archive : std::integral_constant<bool,
1326 std::is_base_of<TextArchive, detail::decay_archive<A>>::value>
1327 { };
1328 } // namespace traits
1329
1330 // ######################################################################
1331 namespace detail
1332 {
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>
1339 {
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 & /*ar*/, construct<T> & /*construct*/ )
1345 { return nullptr; }
1346 };
1347
1348 // no load and construct case
1349 template <class T, class A>
1350 struct Construct<T, A, false, false, false, false>
1351 {
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 "
1358 "{ \n "
1359 " var a; \n "
1360 " ar( a ) \n "
1361 " construct( a ); \n "
1362 "} \n\n" );
1363 static T * load_andor_construct()
1364 { return ::cereal::access::construct<T>(); }
1365 };
1366
1367 // member non-versioned
1368 template <class T, class A>
1369 struct Construct<T, A, true, false, false, false>
1370 {
1371 static void load_andor_construct( A & ar, construct<T> & construct )
1372 {
1373 access::load_and_construct<T>( ar, construct );
1374 }
1375 };
1376
1377 // member versioned
1378 template <class T, class A>
1379 struct Construct<T, A, false, true, false, false>
1380 {
1381 static void load_andor_construct( A & ar, construct<T> & construct )
1382 {
1383 const auto version = ar.template loadClassVersion<T>();
1384 access::load_and_construct<T>( ar, construct, version );
1385 }
1386 };
1387
1388 // non-member non-versioned
1389 template <class T, class A>
1390 struct Construct<T, A, false, false, true, false>
1391 {
1392 static void load_andor_construct( A & ar, construct<T> & construct )
1393 {
1395 }
1396 };
1397
1398 // non-member versioned
1399 template <class T, class A>
1400 struct Construct<T, A, false, false, false, true>
1401 {
1402 static void load_andor_construct( A & ar, construct<T> & construct )
1403 {
1404 const auto version = ar.template loadClassVersion<T>();
1406 }
1407 };
1408 } // namespace detail
1409} // namespace cereal
1410
1411#endif // CEREAL_DETAILS_TRAITS_HPP_
Access control and default construction.
Used to construct types with no default constructor.
Definition: access.hpp:165
Preprocessor macros that can customise the cereal library.
#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME
The deserialization (load_minimal) function name to search for.
Definition: macros.hpp:99
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:85
#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME
The serialization (save_minimal) function name to search for.
Definition: macros.hpp:106
#define CEREAL_SERIALIZE_FUNCTION_NAME
The serialization/deserialization function name to search for.
Definition: macros.hpp:78
A class that allows cereal to load smart pointers to types that have no default constructor.
Definition: access.hpp:109
Definition: traits.hpp:1339
Type traits only struct used to mark an archive as human readable (text based)
Definition: traits.hpp:1321
A type that can implicitly convert to anything else.
Definition: traits.hpp:655
Common base type for base class casting.
Definition: traits.hpp:1167
Used to help strip away conversion wrappers.
Definition: traits.hpp:610
A struct that prevents implicit conversion.
Definition: traits.hpp:619
Source type
Used to get underlying type easily.
Definition: traits.hpp:620
A struct that prevents implicit conversion.
Definition: traits.hpp:637
Source type
Used to get underlying type easily.
Definition: traits.hpp:638
Definition: traits.hpp:1146
The number of input serialization functions available.
Definition: traits.hpp:1134
The number of output serialization functions available.
Definition: traits.hpp:1107
Number of specializations detected.
Definition: traits.hpp:1009
Used to delay a static_assert until template instantiation.
Definition: traits.hpp:57
Definition: traits.hpp:1170
Base class cast, behave as the test.
Definition: traits.hpp:1182
Definition: traits.hpp:405
Definition: traits.hpp:70
Definition: traits.hpp:73
Get the type of the base class of T which inherited from std::enable_shared_from_this.
Definition: traits.hpp:1222
typename std::decay< typename PtrType::element_type >::type type
The type of the base of T that inherited from std::enable_shared_from_this.
Definition: traits.hpp:1227
Non member load and construct check.
Definition: traits.hpp:942
Member load and construct check.
Definition: traits.hpp:899
Definition: traits.hpp:328
Definition: traits.hpp:955
Member load and construct check (versioned)
Definition: traits.hpp:904
Checks to see if the base class used in a cast has a minimal serialization.
Definition: traits.hpp:1196
Definition: traits.hpp:961
Determine if T or any base class of T has inherited from std::enable_shared_from_this.
Definition: traits.hpp:1217
Determines whether the class T can be default constructed by cereal::access.
Definition: traits.hpp:1255
Definition: traits.hpp:1139
Definition: traits.hpp:414
Definition: traits.hpp:1112
Checks if the provided archive type is equal to some cereal archive type.
Definition: traits.hpp:1292
Check if any specialization exists for a type.
Definition: traits.hpp:1021
Checks if an archive is a text archive (human readable)
Definition: traits.hpp:1327
Extracts the true type from something possibly wrapped in a cereal NoConvert.
Definition: traits.hpp:1240
typename detail::DisableIfHelper< Conditions... >::type DisableIf
Provides a way to disable a function if conditions are met.
Definition: traits.hpp:148
#define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name)
Create a test for a cereal::specialization entry.
Definition: traits.hpp:987
#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
#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
#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
typename detail::EnableIfHelper< Conditions... >::type EnableIf
Provides a way to enable a function if conditions are met.
Definition: traits.hpp:116
#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
#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
#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
#define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(test_name, versioned)
Creates a test for whether a non-member load_and_construct specialization exists.
Definition: traits.hpp:910
#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_VERSIONED_TEST
Used to convert a MAKE_HAS_XXX macro into a versioned variant.
Definition: traits.hpp:178
#define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned)
Creates a test for whether a non-member load_minimal function exists.
Definition: traits.hpp:818
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(test_name, versioned)
Creates helpers for minimal save functions.
Definition: traits.hpp:482
sfinae
Return type for SFINAE Enablers.
Definition: traits.hpp:66
#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
typename std::decay< typename strip_minimal< A >::type >::type decay_archive
Removes all qualifiers and minimal wrappers from an archive.
Definition: traits.hpp:1276
#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
#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
#define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name)
Generates a test for specialization for versioned and unversioned functions.
Definition: traits.hpp:1037