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  // ######################################################################
872  // End of serialization existence tests
873  #undef CEREAL_MAKE_VERSIONED_TEST
874 
875  // ######################################################################
876  template <class T, class InputArchive, class OutputArchive>
877  struct has_member_split : std::integral_constant<bool,
878  (has_member_load<T, InputArchive>::value && has_member_save<T, OutputArchive>::value) ||
879  (has_member_versioned_load<T, InputArchive>::value && has_member_versioned_save<T, OutputArchive>::value)> {};
880 
881  // ######################################################################
882  template <class T, class InputArchive, class OutputArchive>
883  struct has_non_member_split : std::integral_constant<bool,
884  (has_non_member_load<T, InputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
885  (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_versioned_save<T, OutputArchive>::value)> {};
886 
887  // ######################################################################
888  template <class T, class OutputArchive>
889  struct has_invalid_output_versioning : std::integral_constant<bool,
890  (has_member_versioned_save<T, OutputArchive>::value && has_member_save<T, OutputArchive>::value) ||
891  (has_non_member_versioned_save<T, OutputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
892  (has_member_versioned_serialize<T, OutputArchive>::value && has_member_serialize<T, OutputArchive>::value) ||
893  (has_non_member_versioned_serialize<T, OutputArchive>::value && has_non_member_serialize<T, OutputArchive>::value) ||
894  (has_member_versioned_save_minimal<T, OutputArchive>::value && has_member_save_minimal<T, OutputArchive>::value) ||
895  (has_non_member_versioned_save_minimal<T, OutputArchive>::value && has_non_member_save_minimal<T, OutputArchive>::value)> {};
896 
897  // ######################################################################
898  template <class T, class InputArchive>
899  struct has_invalid_input_versioning : std::integral_constant<bool,
900  (has_member_versioned_load<T, InputArchive>::value && has_member_load<T, InputArchive>::value) ||
901  (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_load<T, InputArchive>::value) ||
902  (has_member_versioned_serialize<T, InputArchive>::value && has_member_serialize<T, InputArchive>::value) ||
903  (has_non_member_versioned_serialize<T, InputArchive>::value && has_non_member_serialize<T, InputArchive>::value) ||
904  (has_member_versioned_load_minimal<T, InputArchive>::value && has_member_load_minimal<T, InputArchive>::value) ||
905  (has_non_member_versioned_load_minimal<T, InputArchive>::value && has_non_member_load_minimal<T, InputArchive>::value)> {};
906 
907  // ######################################################################
908  namespace detail
909  {
911  #define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name) \
912  template <class T, class A> \
913  struct is_specialized_##name : std::integral_constant<bool, \
914  !std::is_base_of<std::false_type, specialize<A, T, specialization::name>>::value> {}
915 
916  CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_serialize);
917  CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save);
918  CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save_minimal);
919  CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_serialize);
920  CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save);
921  CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save_minimal);
922 
923  #undef CEREAL_MAKE_IS_SPECIALIZED_IMPL
924 
926  template <class T, class A>
927  struct count_specializations : std::integral_constant<int,
928  is_specialized_member_serialize<T, A>::value +
929  is_specialized_member_load_save<T, A>::value +
930  is_specialized_member_load_save_minimal<T, A>::value +
931  is_specialized_non_member_serialize<T, A>::value +
932  is_specialized_non_member_load_save<T, A>::value +
933  is_specialized_non_member_load_save_minimal<T, A>::value> {};
934  } // namespace detail
935 
937  template <class T, class A>
938  struct is_specialized : std::integral_constant<bool,
939  detail::is_specialized_member_serialize<T, A>::value ||
940  detail::is_specialized_member_load_save<T, A>::value ||
941  detail::is_specialized_member_load_save_minimal<T, A>::value ||
942  detail::is_specialized_non_member_serialize<T, A>::value ||
943  detail::is_specialized_non_member_load_save<T, A>::value ||
944  detail::is_specialized_non_member_load_save_minimal<T, A>::value>
945  {
946  static_assert(detail::count_specializations<T, A>::value <= 1, "More than one explicit specialization detected for type.");
947  };
948 
950 
952  #define CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, print_name, spec_name) \
953  static_assert( (is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value && \
954  (has_##name<T, A>::value || has_##versioned_name<T, A>::value)) \
955  || !(is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value), \
956  "cereal detected " #print_name " specialization but no " #print_name " serialize function" )
957 
959 
961  #define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name) \
962  template <class T, class A> \
963  struct is_specialized_##name : std::integral_constant<bool, \
964  is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \
965  { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, name, spec_name); }; \
966  template <class T, class A> \
967  struct is_specialized_##versioned_name : std::integral_constant<bool, \
968  is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \
969  { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, versioned_name, spec_name); }
970 
971  CEREAL_MAKE_IS_SPECIALIZED(member_serialize, member_versioned_serialize, member_serialize);
972  CEREAL_MAKE_IS_SPECIALIZED(non_member_serialize, non_member_versioned_serialize, non_member_serialize);
973 
974  CEREAL_MAKE_IS_SPECIALIZED(member_save, member_versioned_save, member_load_save);
975  CEREAL_MAKE_IS_SPECIALIZED(non_member_save, non_member_versioned_save, non_member_load_save);
976  CEREAL_MAKE_IS_SPECIALIZED(member_load, member_versioned_load, member_load_save);
977  CEREAL_MAKE_IS_SPECIALIZED(non_member_load, non_member_versioned_load, non_member_load_save);
978 
979  CEREAL_MAKE_IS_SPECIALIZED(member_save_minimal, member_versioned_save_minimal, member_load_save_minimal);
980  CEREAL_MAKE_IS_SPECIALIZED(non_member_save_minimal, non_member_versioned_save_minimal, non_member_load_save_minimal);
981  CEREAL_MAKE_IS_SPECIALIZED(member_load_minimal, member_versioned_load_minimal, member_load_save_minimal);
982  CEREAL_MAKE_IS_SPECIALIZED(non_member_load_minimal, non_member_versioned_load_minimal, non_member_load_save_minimal);
983 
984  #undef CEREAL_MAKE_IS_SPECIALIZED_ASSERT
985  #undef CEREAL_MAKE_IS_SPECIALIZED
986 
987  // ######################################################################
988  // detects if a type has any active minimal output serialization
989  template <class T, class OutputArchive>
990  struct has_minimal_output_serialization : std::integral_constant<bool,
991  is_specialized_member_save_minimal<T, OutputArchive>::value ||
992  ((has_member_save_minimal<T, OutputArchive>::value ||
993  has_non_member_save_minimal<T, OutputArchive>::value ||
994  has_member_versioned_save_minimal<T, OutputArchive>::value ||
995  has_non_member_versioned_save_minimal<T, OutputArchive>::value) &&
996  !(is_specialized_member_serialize<T, OutputArchive>::value ||
997  is_specialized_member_save<T, OutputArchive>::value))> {};
998 
999  // ######################################################################
1000  // detects if a type has any active minimal input serialization
1001  template <class T, class InputArchive>
1002  struct has_minimal_input_serialization : std::integral_constant<bool,
1003  is_specialized_member_load_minimal<T, InputArchive>::value ||
1004  ((has_member_load_minimal<T, InputArchive>::value ||
1005  has_non_member_load_minimal<T, InputArchive>::value ||
1006  has_member_versioned_load_minimal<T, InputArchive>::value ||
1007  has_non_member_versioned_load_minimal<T, InputArchive>::value) &&
1008  !(is_specialized_member_serialize<T, InputArchive>::value ||
1009  is_specialized_member_load<T, InputArchive>::value))> {};
1010 
1011  // ######################################################################
1012  namespace detail
1013  {
1015 
1016  template <class T, class OutputArchive>
1017  struct count_output_serializers : std::integral_constant<int,
1018  count_specializations<T, OutputArchive>::value ? count_specializations<T, OutputArchive>::value :
1019  has_member_save<T, OutputArchive>::value +
1020  has_non_member_save<T, OutputArchive>::value +
1021  has_member_serialize<T, OutputArchive>::value +
1022  has_non_member_serialize<T, OutputArchive>::value +
1023  has_member_save_minimal<T, OutputArchive>::value +
1024  has_non_member_save_minimal<T, OutputArchive>::value +
1025  /*-versioned---------------------------------------------------------*/
1026  has_member_versioned_save<T, OutputArchive>::value +
1027  has_non_member_versioned_save<T, OutputArchive>::value +
1028  has_member_versioned_serialize<T, OutputArchive>::value +
1029  has_non_member_versioned_serialize<T, OutputArchive>::value +
1030  has_member_versioned_save_minimal<T, OutputArchive>::value +
1031  has_non_member_versioned_save_minimal<T, OutputArchive>::value> {};
1032  }
1033 
1034  template <class T, class OutputArchive>
1035  struct is_output_serializable : std::integral_constant<bool,
1036  detail::count_output_serializers<T, OutputArchive>::value == 1> {};
1037 
1038  // ######################################################################
1039  namespace detail
1040  {
1042 
1043  template <class T, class InputArchive>
1044  struct count_input_serializers : std::integral_constant<int,
1045  count_specializations<T, InputArchive>::value ? count_specializations<T, InputArchive>::value :
1046  has_member_load<T, InputArchive>::value +
1047  has_non_member_load<T, InputArchive>::value +
1048  has_member_serialize<T, InputArchive>::value +
1049  has_non_member_serialize<T, InputArchive>::value +
1050  has_member_load_minimal<T, InputArchive>::value +
1051  has_non_member_load_minimal<T, InputArchive>::value +
1052  /*-versioned---------------------------------------------------------*/
1053  has_member_versioned_load<T, InputArchive>::value +
1054  has_non_member_versioned_load<T, InputArchive>::value +
1055  has_member_versioned_serialize<T, InputArchive>::value +
1056  has_non_member_versioned_serialize<T, InputArchive>::value +
1057  has_member_versioned_load_minimal<T, InputArchive>::value +
1058  has_non_member_versioned_load_minimal<T, InputArchive>::value> {};
1059  }
1060 
1061  template <class T, class InputArchive>
1062  struct is_input_serializable : std::integral_constant<bool,
1063  detail::count_input_serializers<T, InputArchive>::value == 1> {};
1064 
1065  // ######################################################################
1066  // Base Class Support
1067  namespace detail
1068  {
1070  {
1071  template<class T>
1072  base_class_id(T const * const t) :
1073  type(typeid(T)),
1074  ptr(t),
1075  hash(std::hash<std::type_index>()(typeid(T)) ^ (std::hash<void const *>()(t) << 1))
1076  { }
1077 
1078  bool operator==(base_class_id const & other) const
1079  { return (type == other.type) && (ptr == other.ptr); }
1080 
1081  std::type_index type;
1082  void const * ptr;
1083  size_t hash;
1084  };
1085  struct base_class_id_hash { size_t operator()(base_class_id const & id) const { return id.hash; } };
1086  } // namespace detail
1087 
1088  namespace detail
1089  {
1091  struct BaseCastBase {};
1092 
1093  template <class>
1095 
1096  template <template<typename> class Cast, class Base>
1097  struct get_base_class<Cast<Base>>
1098  {
1099  using type = Base;
1100  };
1101 
1103  template <class Cast, template<class, class> class Test, class Archive,
1104  bool IsBaseCast = std::is_base_of<BaseCastBase, Cast>::value>
1105  struct has_minimal_base_class_serialization_impl : Test<typename get_base_class<Cast>::type, Archive>
1106  { };
1107 
1109  template <class Cast, template<class, class> class Test, class Archive>
1110  struct has_minimal_base_class_serialization_impl<Cast,Test, Archive, false> : std::false_type
1111  { };
1112  }
1113 
1115 
1118  template <class Cast, template<class, class> class Test, class Archive>
1120  { };
1121 
1122 
1123  // ######################################################################
1124  namespace detail
1125  {
1127  {
1128  template <class U>
1129  static auto check( U const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() );
1130 
1131  static auto check( ... ) -> decltype( std::false_type() );
1132 
1133  template <class U>
1134  static auto get( U const & t ) -> decltype( t.shared_from_this() );
1135  };
1136  }
1137 
1139  template<class T>
1140  struct has_shared_from_this : decltype(detail::shared_from_this_wrapper::check(std::declval<T>()))
1141  { };
1142 
1144  template <class T>
1146  {
1147  private:
1148  using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
1149  public:
1151  using type = typename std::decay<typename PtrType::element_type>::type;
1152  };
1153 
1154  // ######################################################################
1156 
1162  template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
1164  {
1165  using type = T;
1166  };
1167 
1169  template <class T>
1170  struct strip_minimal<T, true>
1171  {
1172  using type = typename T::type;
1173  };
1174 
1175  // ######################################################################
1177  template<typename T, typename A>
1178  struct has_member_load_and_construct : std::integral_constant<bool,
1179  std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
1180  { };
1181 
1182  // ######################################################################
1184  template<typename T, typename A>
1185  struct has_non_member_load_and_construct : std::integral_constant<bool,
1186  std::is_same<decltype( LoadAndConstruct<T>::load_and_construct( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
1187  { };
1188 
1189  // ######################################################################
1191  template<typename T, typename A>
1192  struct has_load_and_construct : std::integral_constant<bool,
1193  has_member_load_and_construct<T, A>::value || has_non_member_load_and_construct<T, A>::value>
1194  { };
1195 
1196  // ######################################################################
1198  template <class T>
1200  {
1201  #ifdef CEREAL_OLDER_GCC
1202  template <class TT, class SFINAE = void>
1203  struct test : no {};
1204  template <class TT>
1205  struct test<TT, typename detail::Void< decltype( cereal::access::construct<TT>() ) >::type> : yes {};
1206  static const bool value = test<T>();
1207  #else // NOT CEREAL_OLDER_GCC =========================================
1208  template <class TT>
1209  static auto test(int) -> decltype( cereal::access::construct<TT>(), yes());
1210  template <class>
1211  static no test(...);
1212  static const bool value = std::is_same<decltype(test<T>(0)), yes>::value;
1213  #endif // NOT CEREAL_OLDER_GCC
1214  };
1215 
1216  // ######################################################################
1217  namespace detail
1218  {
1220  template <class A>
1221  using decay_archive = typename std::decay<typename strip_minimal<A>::type>::type;
1222  }
1223 
1225 
1234  template <class ArchiveT, class CerealArchiveT>
1235  struct is_same_archive : std::integral_constant<bool,
1236  std::is_same<detail::decay_archive<ArchiveT>, CerealArchiveT>::value>
1237  { };
1238 
1239  // ######################################################################
1241 
1260  #define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \
1261  typename std::enable_if<cereal::traits::is_same_archive<Archive, INTYPE>::value || cereal::traits::is_same_archive<Archive, OUTTYPE>::value, void>::type
1262 
1264 
1266  struct TextArchive {};
1267 
1269  template <class A>
1270  struct is_text_archive : std::integral_constant<bool,
1271  std::is_base_of<TextArchive, detail::decay_archive<A>>::value>
1272  { };
1273  } // namespace traits
1274 
1275  // ######################################################################
1276  namespace detail
1277  {
1278  template <class T, class A, bool Member = traits::has_member_load_and_construct<T, A>::value, bool NonMember = traits::has_non_member_load_and_construct<T, A>::value>
1279  struct Construct
1280  {
1282  "Cereal detected both member and non member load_and_construct functions!" );
1283  static T * load_andor_construct( A & /*ar*/, construct<T> & /*construct*/ )
1284  { return nullptr; }
1285  };
1286 
1287  template <class T, class A>
1288  struct Construct<T, A, false, false>
1289  {
1291  "Trying to serialize a an object with no default constructor. \n\n "
1292  "Types must either be default constructible or define either a member or non member Construct function. \n "
1293  "Construct functions generally have the signature: \n\n "
1294  "template <class Archive> \n "
1295  "static void load_and_construct(Archive & ar, cereal::construct<T> & construct) \n "
1296  "{ \n "
1297  " var a; \n "
1298  " ar( a ) \n "
1299  " construct( a ); \n "
1300  "} \n\n" );
1301  static T * load_andor_construct()
1302  { return ::cereal::access::construct<T>(); }
1303  };
1304 
1305  template <class T, class A>
1306  struct Construct<T, A, true, false>
1307  {
1308  static void load_andor_construct( A & ar, construct<T> & construct )
1309  {
1310  access::load_and_construct<T>( ar, construct );
1311  }
1312  };
1313 
1314  template <class T, class A>
1315  struct Construct<T, A, false, true>
1316  {
1317  static void load_andor_construct( A & ar, construct<T> & construct )
1318  {
1319  LoadAndConstruct<T>::load_and_construct( ar, construct );
1320  }
1321  };
1322  } // namespace detail
1323 } // namespace cereal
1324 
1325 #endif // CEREAL_DETAILS_TRAITS_HPP_
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(test_name)
Creates a test for whether a member save_minimal function exists.
Definition: traits.hpp:502
Has either a member or non member allocate.
Definition: traits.hpp:1192
Definition: traits.hpp:413
Check if any specialization exists for a type.
Definition: traits.hpp:938
Determines whether the class T can be default constructed by cereal::access.
Definition: traits.hpp:1199
Extracts the true type from something possibly wrapped in a cereal NoConvert.
Definition: traits.hpp:1163
The number of output serialization functions available.
Definition: traits.hpp:1017
Common base type for base class casting.
Definition: traits.hpp:1091
Source type
Used to get underlying type easily.
Definition: traits.hpp:638
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:1119
Used to construct types with no default constructor.
Definition: access.hpp:151
static std::false_type load_and_construct(...)
Called by cereal if no default constructor exists to load and construct data simultaneously.
Definition: access.hpp:95
Checks if the provided archive type is equal to some cereal archive type.
Definition: traits.hpp:1235
STL namespace.
Type traits only struct used to mark an archive as human readable (text based)
Definition: traits.hpp:1266
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_test_name, load_test_prefix)
Creates a test for whether a member load_minimal function exists.
Definition: traits.hpp:764
#define CEREAL_SERIALIZE_FUNCTION_NAME
The serialization/deserialization function name to search for.
Definition: macros.hpp:51
typename std::decay< typename PtrType::element_type >::type type
The type of the base of T that inherited from std::enable_shared_from_this.
Definition: traits.hpp:1151
A struct that prevents implicit conversion.
Definition: traits.hpp:636
Source type
Used to get underlying type easily.
Definition: traits.hpp:620
#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME
The serialization (save_minimal) function name to search for.
Definition: macros.hpp:79
A struct that prevents implicit conversion.
Definition: traits.hpp:618
#define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(test_name, versioned)
Creates a test for whether a non-member save function exists.
Definition: traits.hpp:358
Checks if an archive is a text archive (human readable)
Definition: traits.hpp:1270
#define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name)
Generates a test for specialization for versioned and unversioned functions.
Definition: traits.hpp:961
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned)
Creates implementation details for whether a member save_minimal function exists. ...
Definition: traits.hpp:449
Definition: traits.hpp:877
The number of input serialization functions available.
Definition: traits.hpp:1044
Member load and construct check.
Definition: traits.hpp:1178
#define CEREAL_MAKE_HAS_NON_MEMBER_TEST(test_name, func, versioned)
Creates a test for whether a non const non-member function exists.
Definition: traits.hpp:217
Determine if T or any base class of T has inherited from std::enable_shared_from_this.
Definition: traits.hpp:1140
Get the type of the base class of T which inherited from std::enable_shared_from_this.
Definition: traits.hpp:1145
Definition: access.hpp:39
#define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned)
Creates a test for whether a non-member load_minimal function exists.
Definition: traits.hpp:806
typename std::decay< typename strip_minimal< A >::type >::type decay_archive
Removes all qualifiers and minimal wrappers from an archive.
Definition: traits.hpp:1221
Access control, default construction, and serialization disambiguation.
sfinae
Return type for SFINAE Enablers.
Definition: traits.hpp:66
Definition: traits.hpp:1035
#define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name)
Create a test for a cereal::specialization entry.
Definition: traits.hpp:911
Definition: traits.hpp:883
Preprocessor macros that can customise the cereal library.
#define CEREAL_LOAD_FUNCTION_NAME
The deserialization (load) function name to search for.
Definition: macros.hpp:58
#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME
The deserialization (load_minimal) function name to search for.
Definition: macros.hpp:72
Used to help strip away conversion wrappers.
Definition: traits.hpp:610
Number of specializations detected.
Definition: traits.hpp:927
A type that can implicitly convert to anything else.
Definition: traits.hpp:654
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned)
Creates a test for whether a member load_minimal function exists.
Definition: traits.hpp:692
#define CEREAL_MAKE_VERSIONED_TEST
Used to convert a MAKE_HAS_XXX macro into a versioned variant.
Definition: traits.hpp:178
Definition: traits.hpp:405
#define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned)
Creates a test for whether a member save function exists.
Definition: traits.hpp:300
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_test_name, save_test_name, save_test_prefix, versioned)
Creates helpers for minimal load functions.
Definition: traits.hpp:731
Base class cast, behave as the test.
Definition: traits.hpp:1105
#define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned)
Creates a test for whether a non const member function exists.
Definition: traits.hpp:196
#define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(test_name, versioned)
Creates a test for whether a non-member save_minimal function exists.
Definition: traits.hpp:541
Definition: traits.hpp:1279
Definition: traits.hpp:70
Definition: traits.hpp:1094
Definition: traits.hpp:1062
Non member load and construct check.
Definition: traits.hpp:1185
Definition: traits.hpp:1069
typename detail::DisableIfHelper< Conditions... >::type DisableIf
Provides a way to disable a function if conditions are met.
Definition: traits.hpp:148
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(test_name, versioned)
Creates helpers for minimal save functions.
Definition: traits.hpp:482
Definition: traits.hpp:327