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 cereal 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 RANDOLPH VOORHIES OR SHANE GRANT 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 
45 namespace 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 
654  struct AnyConvert
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, )
773  CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_minimal, load)
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 
806  #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned) \
807  namespace detail \
808  { \
809  template <class T, class A, class U = void> \
810  struct has_non_member_##test_name##_impl \
811  { \
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; \
817  \
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; \
823  \
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; \
829  }; \
830  \
831  template <class T, class A, bool Valid> \
832  struct has_non_member_##test_name##_wrapper : std::false_type {}; \
833  \
834  template <class T, class A> \
835  struct has_non_member_##test_name##_wrapper<T, A, true> \
836  { \
837  using AOut = typename detail::get_output_from_input<A>::type; \
838  \
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 "." ); \
842  \
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; \
846  \
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" ); \
853  }; \
854  } /* namespace detail */ \
855  \
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> {};
859 
860  // ######################################################################
861  // Non-Member Load Minimal
862  CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(load_minimal, save_minimal, )
863 
864  // ######################################################################
865  // Non-Member Load Minimal (versioned)
866  CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
867 
868  // ######################################################################
869  #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST
870 
871  // ######################################################################
873  template<typename T, typename A>
874  struct has_member_load_and_construct : std::integral_constant<bool,
875  std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
876  { };
877 
878  // ######################################################################
880  template<typename T, typename A>
881  struct has_member_versioned_load_and_construct : std::integral_constant<bool,
882  std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>(), 0 ) ), void>::value>
883  { };
884 
885  // ######################################################################
887 
889  #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(test_name, versioned) \
890  namespace detail \
891  { \
892  template <class T, class A> \
893  struct has_non_member_##test_name##_impl \
894  { \
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; \
901  }; \
902  } /* end namespace detail */ \
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> {};
905 
906  // ######################################################################
909 
910  // ######################################################################
913 
914  // ######################################################################
916  template<typename T, typename A>
917  struct has_load_and_construct : std::integral_constant<bool,
918  has_member_load_and_construct<T, A>::value || has_non_member_load_and_construct<T, A>::value ||
919  has_member_versioned_load_and_construct<T, A>::value || has_non_member_versioned_load_and_construct<T, A>::value>
920  { };
921 
922  // ######################################################################
923  #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST
924 
925  // ######################################################################
926  // End of serialization existence tests
927  #undef CEREAL_MAKE_VERSIONED_TEST
928 
929  // ######################################################################
930  template <class T, class InputArchive, class OutputArchive>
931  struct has_member_split : std::integral_constant<bool,
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)> {};
934 
935  // ######################################################################
936  template <class T, class InputArchive, class OutputArchive>
937  struct has_non_member_split : std::integral_constant<bool,
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)> {};
940 
941  // ######################################################################
942  template <class T, class OutputArchive>
943  struct has_invalid_output_versioning : std::integral_constant<bool,
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)> {};
950 
951  // ######################################################################
952  template <class T, class InputArchive>
953  struct has_invalid_input_versioning : std::integral_constant<bool,
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)> {};
960 
961  // ######################################################################
962  namespace detail
963  {
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> {}
969 
970  CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_serialize);
971  CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save);
972  CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save_minimal);
973  CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_serialize);
974  CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save);
975  CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save_minimal);
976 
977  #undef CEREAL_MAKE_IS_SPECIALIZED_IMPL
978 
980  template <class T, class A>
981  struct count_specializations : std::integral_constant<int,
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> {};
988  } // namespace detail
989 
991  template <class T, class A>
992  struct is_specialized : std::integral_constant<bool,
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>
999  {
1000  static_assert(detail::count_specializations<T, A>::value <= 1, "More than one explicit specialization detected for type.");
1001  };
1002 
1004 
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" )
1011 
1013 
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); }
1024 
1025  CEREAL_MAKE_IS_SPECIALIZED(member_serialize, member_versioned_serialize, member_serialize);
1026  CEREAL_MAKE_IS_SPECIALIZED(non_member_serialize, non_member_versioned_serialize, non_member_serialize);
1027 
1028  CEREAL_MAKE_IS_SPECIALIZED(member_save, member_versioned_save, member_load_save);
1029  CEREAL_MAKE_IS_SPECIALIZED(non_member_save, non_member_versioned_save, non_member_load_save);
1030  CEREAL_MAKE_IS_SPECIALIZED(member_load, member_versioned_load, member_load_save);
1031  CEREAL_MAKE_IS_SPECIALIZED(non_member_load, non_member_versioned_load, non_member_load_save);
1032 
1033  CEREAL_MAKE_IS_SPECIALIZED(member_save_minimal, member_versioned_save_minimal, member_load_save_minimal);
1034  CEREAL_MAKE_IS_SPECIALIZED(non_member_save_minimal, non_member_versioned_save_minimal, non_member_load_save_minimal);
1035  CEREAL_MAKE_IS_SPECIALIZED(member_load_minimal, member_versioned_load_minimal, member_load_save_minimal);
1036  CEREAL_MAKE_IS_SPECIALIZED(non_member_load_minimal, non_member_versioned_load_minimal, non_member_load_save_minimal);
1037 
1038  #undef CEREAL_MAKE_IS_SPECIALIZED_ASSERT
1039  #undef CEREAL_MAKE_IS_SPECIALIZED
1040 
1041  // ######################################################################
1042  // detects if a type has any active minimal output serialization
1043  template <class T, class OutputArchive>
1044  struct has_minimal_output_serialization : std::integral_constant<bool,
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))> {};
1052 
1053  // ######################################################################
1054  // detects if a type has any active minimal input serialization
1055  template <class T, class InputArchive>
1056  struct has_minimal_input_serialization : std::integral_constant<bool,
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))> {};
1064 
1065  // ######################################################################
1066  namespace detail
1067  {
1069 
1070  template <class T, class OutputArchive>
1071  struct count_output_serializers : std::integral_constant<int,
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 +
1079  /*-versioned---------------------------------------------------------*/
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> {};
1086  }
1087 
1088  template <class T, class OutputArchive>
1089  struct is_output_serializable : std::integral_constant<bool,
1090  detail::count_output_serializers<T, OutputArchive>::value == 1> {};
1091 
1092  // ######################################################################
1093  namespace detail
1094  {
1096 
1097  template <class T, class InputArchive>
1098  struct count_input_serializers : std::integral_constant<int,
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 +
1106  /*-versioned---------------------------------------------------------*/
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> {};
1113  }
1114 
1115  template <class T, class InputArchive>
1116  struct is_input_serializable : std::integral_constant<bool,
1117  detail::count_input_serializers<T, InputArchive>::value == 1> {};
1118 
1119  // ######################################################################
1120  // Base Class Support
1121  namespace detail
1122  {
1124  {
1125  template<class T>
1126  base_class_id(T const * const t) :
1127  type(typeid(T)),
1128  ptr(t),
1129  hash(std::hash<std::type_index>()(typeid(T)) ^ (std::hash<void const *>()(t) << 1))
1130  { }
1131 
1132  bool operator==(base_class_id const & other) const
1133  { return (type == other.type) && (ptr == other.ptr); }
1134 
1135  std::type_index type;
1136  void const * ptr;
1137  size_t hash;
1138  };
1139  struct base_class_id_hash { size_t operator()(base_class_id const & id) const { return id.hash; } };
1140  } // namespace detail
1141 
1142  namespace detail
1143  {
1145  struct BaseCastBase {};
1146 
1147  template <class>
1149 
1150  template <template<typename> class Cast, class Base>
1151  struct get_base_class<Cast<Base>>
1152  {
1153  using type = Base;
1154  };
1155 
1157  template <class Cast, template<class, class> class Test, class Archive,
1158  bool IsBaseCast = std::is_base_of<BaseCastBase, Cast>::value>
1159  struct has_minimal_base_class_serialization_impl : Test<typename get_base_class<Cast>::type, Archive>
1160  { };
1161 
1163  template <class Cast, template<class, class> class Test, class Archive>
1164  struct has_minimal_base_class_serialization_impl<Cast,Test, Archive, false> : std::false_type
1165  { };
1166  }
1167 
1169 
1172  template <class Cast, template<class, class> class Test, class Archive>
1174  { };
1175 
1176 
1177  // ######################################################################
1178  namespace detail
1179  {
1181  {
1182  template <class U>
1183  static auto (check)( U const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() );
1184 
1185  static auto (check)( ... ) -> decltype( std::false_type() );
1186 
1187  template <class U>
1188  static auto get( U const & t ) -> decltype( t.shared_from_this() );
1189  };
1190  }
1191 
1193  template<class T>
1194  struct has_shared_from_this : decltype((detail::shared_from_this_wrapper::check)(std::declval<T>()))
1195  { };
1196 
1198  template <class T>
1200  {
1201  private:
1202  using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
1203  public:
1205  using type = typename std::decay<typename PtrType::element_type>::type;
1206  };
1207 
1208  // ######################################################################
1210 
1216  template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
1218  {
1219  using type = T;
1220  };
1221 
1223  template <class T>
1224  struct strip_minimal<T, true>
1225  {
1226  using type = typename T::type;
1227  };
1228 
1229  // ######################################################################
1231  template <class T>
1233  {
1234  #ifdef CEREAL_OLDER_GCC
1235  template <class TT, class SFINAE = void>
1236  struct test : no {};
1237  template <class TT>
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 =========================================
1241  template <class TT>
1242  static auto test(int) -> decltype( cereal::access::construct<TT>(), yes());
1243  template <class>
1244  static no test(...);
1245  static const bool value = std::is_same<decltype(test<T>(0)), yes>::value;
1246  #endif // NOT CEREAL_OLDER_GCC
1247  };
1248 
1249  // ######################################################################
1250  namespace detail
1251  {
1253  template <class A>
1254  using decay_archive = typename std::decay<typename strip_minimal<A>::type>::type;
1255  }
1256 
1258 
1267  template <class ArchiveT, class CerealArchiveT>
1268  struct is_same_archive : std::integral_constant<bool,
1269  std::is_same<detail::decay_archive<ArchiveT>, CerealArchiveT>::value>
1270  { };
1271 
1272  // ######################################################################
1274 
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
1295 
1297 
1299  struct TextArchive {};
1300 
1302  template <class A>
1303  struct is_text_archive : std::integral_constant<bool,
1304  std::is_base_of<TextArchive, detail::decay_archive<A>>::value>
1305  { };
1306  } // namespace traits
1307 
1308  // ######################################################################
1309  namespace detail
1310  {
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>
1316  struct Construct
1317  {
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 & /*ar*/, construct<T> & /*construct*/ )
1323  { return nullptr; }
1324  };
1325 
1326  // no load and construct case
1327  template <class T, class A>
1328  struct Construct<T, A, false, false, false, false>
1329  {
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 "
1336  "{ \n "
1337  " var a; \n "
1338  " ar( a ) \n "
1339  " construct( a ); \n "
1340  "} \n\n" );
1341  static T * load_andor_construct()
1342  { return ::cereal::access::construct<T>(); }
1343  };
1344 
1345  // member non-versioned
1346  template <class T, class A>
1347  struct Construct<T, A, true, false, false, false>
1348  {
1349  static void load_andor_construct( A & ar, construct<T> & construct )
1350  {
1351  access::load_and_construct<T>( ar, construct );
1352  }
1353  };
1354 
1355  // member versioned
1356  template <class T, class A>
1357  struct Construct<T, A, false, true, false, false>
1358  {
1359  static void load_andor_construct( A & ar, construct<T> & construct )
1360  {
1361  const auto version = ar.template loadClassVersion<T>();
1362  access::load_and_construct<T>( ar, construct, version );
1363  }
1364  };
1365 
1366  // non-member non-versioned
1367  template <class T, class A>
1368  struct Construct<T, A, false, false, true, false>
1369  {
1370  static void load_andor_construct( A & ar, construct<T> & construct )
1371  {
1372  LoadAndConstruct<T>::load_and_construct( ar, construct );
1373  }
1374  };
1375 
1376  // non-member versioned
1377  template <class T, class A>
1378  struct Construct<T, A, false, false, false, true>
1379  {
1380  static void load_andor_construct( A & ar, construct<T> & construct )
1381  {
1382  const auto version = ar.template loadClassVersion<T>();
1383  LoadAndConstruct<T>::load_and_construct( ar, construct, version );
1384  }
1385  };
1386  } // namespace detail
1387 } // namespace cereal
1388 
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:413
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
Definition: traits.hpp:73
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
STL namespace.
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
#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
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
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
The number of input serialization functions available.
Definition: traits.hpp:1098
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: 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
Access control, default construction, and serialization disambiguation.
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
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:70
Definition: traits.hpp:1148
Definition: traits.hpp:1116
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