isotree 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/LICENSE.txt +2 -2
  4. data/README.md +22 -1
  5. data/ext/isotree/ext.cpp +26 -0
  6. data/ext/isotree/extconf.rb +3 -3
  7. data/lib/isotree.rb +1 -0
  8. data/lib/isotree/isolation_forest.rb +86 -1
  9. data/lib/isotree/version.rb +1 -1
  10. data/vendor/cereal/LICENSE +24 -0
  11. data/vendor/cereal/README.md +85 -0
  12. data/vendor/cereal/include/cereal/access.hpp +351 -0
  13. data/vendor/cereal/include/cereal/archives/adapters.hpp +163 -0
  14. data/vendor/cereal/include/cereal/archives/binary.hpp +169 -0
  15. data/vendor/cereal/include/cereal/archives/json.hpp +1019 -0
  16. data/vendor/cereal/include/cereal/archives/portable_binary.hpp +334 -0
  17. data/vendor/cereal/include/cereal/archives/xml.hpp +956 -0
  18. data/vendor/cereal/include/cereal/cereal.hpp +1089 -0
  19. data/vendor/cereal/include/cereal/details/helpers.hpp +422 -0
  20. data/vendor/cereal/include/cereal/details/polymorphic_impl.hpp +796 -0
  21. data/vendor/cereal/include/cereal/details/polymorphic_impl_fwd.hpp +65 -0
  22. data/vendor/cereal/include/cereal/details/static_object.hpp +127 -0
  23. data/vendor/cereal/include/cereal/details/traits.hpp +1411 -0
  24. data/vendor/cereal/include/cereal/details/util.hpp +84 -0
  25. data/vendor/cereal/include/cereal/external/base64.hpp +134 -0
  26. data/vendor/cereal/include/cereal/external/rapidjson/allocators.h +284 -0
  27. data/vendor/cereal/include/cereal/external/rapidjson/cursorstreamwrapper.h +78 -0
  28. data/vendor/cereal/include/cereal/external/rapidjson/document.h +2652 -0
  29. data/vendor/cereal/include/cereal/external/rapidjson/encodedstream.h +299 -0
  30. data/vendor/cereal/include/cereal/external/rapidjson/encodings.h +716 -0
  31. data/vendor/cereal/include/cereal/external/rapidjson/error/en.h +74 -0
  32. data/vendor/cereal/include/cereal/external/rapidjson/error/error.h +161 -0
  33. data/vendor/cereal/include/cereal/external/rapidjson/filereadstream.h +99 -0
  34. data/vendor/cereal/include/cereal/external/rapidjson/filewritestream.h +104 -0
  35. data/vendor/cereal/include/cereal/external/rapidjson/fwd.h +151 -0
  36. data/vendor/cereal/include/cereal/external/rapidjson/internal/biginteger.h +290 -0
  37. data/vendor/cereal/include/cereal/external/rapidjson/internal/diyfp.h +271 -0
  38. data/vendor/cereal/include/cereal/external/rapidjson/internal/dtoa.h +245 -0
  39. data/vendor/cereal/include/cereal/external/rapidjson/internal/ieee754.h +78 -0
  40. data/vendor/cereal/include/cereal/external/rapidjson/internal/itoa.h +308 -0
  41. data/vendor/cereal/include/cereal/external/rapidjson/internal/meta.h +186 -0
  42. data/vendor/cereal/include/cereal/external/rapidjson/internal/pow10.h +55 -0
  43. data/vendor/cereal/include/cereal/external/rapidjson/internal/regex.h +740 -0
  44. data/vendor/cereal/include/cereal/external/rapidjson/internal/stack.h +232 -0
  45. data/vendor/cereal/include/cereal/external/rapidjson/internal/strfunc.h +69 -0
  46. data/vendor/cereal/include/cereal/external/rapidjson/internal/strtod.h +290 -0
  47. data/vendor/cereal/include/cereal/external/rapidjson/internal/swap.h +46 -0
  48. data/vendor/cereal/include/cereal/external/rapidjson/istreamwrapper.h +128 -0
  49. data/vendor/cereal/include/cereal/external/rapidjson/memorybuffer.h +70 -0
  50. data/vendor/cereal/include/cereal/external/rapidjson/memorystream.h +71 -0
  51. data/vendor/cereal/include/cereal/external/rapidjson/msinttypes/inttypes.h +316 -0
  52. data/vendor/cereal/include/cereal/external/rapidjson/msinttypes/stdint.h +300 -0
  53. data/vendor/cereal/include/cereal/external/rapidjson/ostreamwrapper.h +81 -0
  54. data/vendor/cereal/include/cereal/external/rapidjson/pointer.h +1414 -0
  55. data/vendor/cereal/include/cereal/external/rapidjson/prettywriter.h +277 -0
  56. data/vendor/cereal/include/cereal/external/rapidjson/rapidjson.h +656 -0
  57. data/vendor/cereal/include/cereal/external/rapidjson/reader.h +2230 -0
  58. data/vendor/cereal/include/cereal/external/rapidjson/schema.h +2497 -0
  59. data/vendor/cereal/include/cereal/external/rapidjson/stream.h +223 -0
  60. data/vendor/cereal/include/cereal/external/rapidjson/stringbuffer.h +121 -0
  61. data/vendor/cereal/include/cereal/external/rapidjson/writer.h +709 -0
  62. data/vendor/cereal/include/cereal/external/rapidxml/license.txt +52 -0
  63. data/vendor/cereal/include/cereal/external/rapidxml/manual.html +406 -0
  64. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml.hpp +2624 -0
  65. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_iterators.hpp +175 -0
  66. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_print.hpp +428 -0
  67. data/vendor/cereal/include/cereal/external/rapidxml/rapidxml_utils.hpp +123 -0
  68. data/vendor/cereal/include/cereal/macros.hpp +154 -0
  69. data/vendor/cereal/include/cereal/specialize.hpp +139 -0
  70. data/vendor/cereal/include/cereal/types/array.hpp +79 -0
  71. data/vendor/cereal/include/cereal/types/atomic.hpp +55 -0
  72. data/vendor/cereal/include/cereal/types/base_class.hpp +203 -0
  73. data/vendor/cereal/include/cereal/types/bitset.hpp +176 -0
  74. data/vendor/cereal/include/cereal/types/boost_variant.hpp +164 -0
  75. data/vendor/cereal/include/cereal/types/chrono.hpp +72 -0
  76. data/vendor/cereal/include/cereal/types/common.hpp +129 -0
  77. data/vendor/cereal/include/cereal/types/complex.hpp +56 -0
  78. data/vendor/cereal/include/cereal/types/concepts/pair_associative_container.hpp +73 -0
  79. data/vendor/cereal/include/cereal/types/deque.hpp +62 -0
  80. data/vendor/cereal/include/cereal/types/forward_list.hpp +68 -0
  81. data/vendor/cereal/include/cereal/types/functional.hpp +43 -0
  82. data/vendor/cereal/include/cereal/types/list.hpp +62 -0
  83. data/vendor/cereal/include/cereal/types/map.hpp +36 -0
  84. data/vendor/cereal/include/cereal/types/memory.hpp +425 -0
  85. data/vendor/cereal/include/cereal/types/optional.hpp +66 -0
  86. data/vendor/cereal/include/cereal/types/polymorphic.hpp +483 -0
  87. data/vendor/cereal/include/cereal/types/queue.hpp +132 -0
  88. data/vendor/cereal/include/cereal/types/set.hpp +103 -0
  89. data/vendor/cereal/include/cereal/types/stack.hpp +76 -0
  90. data/vendor/cereal/include/cereal/types/string.hpp +61 -0
  91. data/vendor/cereal/include/cereal/types/tuple.hpp +123 -0
  92. data/vendor/cereal/include/cereal/types/unordered_map.hpp +36 -0
  93. data/vendor/cereal/include/cereal/types/unordered_set.hpp +99 -0
  94. data/vendor/cereal/include/cereal/types/utility.hpp +47 -0
  95. data/vendor/cereal/include/cereal/types/valarray.hpp +89 -0
  96. data/vendor/cereal/include/cereal/types/variant.hpp +109 -0
  97. data/vendor/cereal/include/cereal/types/vector.hpp +112 -0
  98. data/vendor/cereal/include/cereal/version.hpp +52 -0
  99. data/vendor/isotree/LICENSE +1 -1
  100. data/vendor/isotree/README.md +2 -1
  101. data/vendor/isotree/src/RcppExports.cpp +44 -4
  102. data/vendor/isotree/src/Rwrapper.cpp +141 -51
  103. data/vendor/isotree/src/crit.cpp +1 -1
  104. data/vendor/isotree/src/dealloc.cpp +1 -1
  105. data/vendor/isotree/src/dist.cpp +6 -6
  106. data/vendor/isotree/src/extended.cpp +5 -5
  107. data/vendor/isotree/src/fit_model.cpp +30 -19
  108. data/vendor/isotree/src/helpers_iforest.cpp +26 -11
  109. data/vendor/isotree/src/impute.cpp +7 -7
  110. data/vendor/isotree/src/isoforest.cpp +7 -7
  111. data/vendor/isotree/src/isotree.hpp +27 -5
  112. data/vendor/isotree/src/merge_models.cpp +1 -1
  113. data/vendor/isotree/src/mult.cpp +1 -1
  114. data/vendor/isotree/src/predict.cpp +20 -16
  115. data/vendor/isotree/src/serialize.cpp +1 -1
  116. data/vendor/isotree/src/sql.cpp +545 -0
  117. data/vendor/isotree/src/utils.cpp +36 -44
  118. metadata +98 -92
@@ -0,0 +1,65 @@
1
+ /*! \file polymorphic_impl_fwd.hpp
2
+ \brief Internal polymorphism support forward declarations
3
+ \ingroup Internal */
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
+
31
+ /* This code is heavily inspired by the boost serialization implementation by the following authors
32
+
33
+ (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
34
+ Use, modification and distribution is subject to the Boost Software
35
+ License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt)
36
+
37
+ See http://www.boost.org for updates, documentation, and revision history.
38
+
39
+ (C) Copyright 2006 David Abrahams - http://www.boost.org.
40
+
41
+ See /boost/serialization/export.hpp and /boost/archive/detail/register_archive.hpp for their
42
+ implementation.
43
+ */
44
+
45
+ #ifndef CEREAL_DETAILS_POLYMORPHIC_IMPL_FWD_HPP_
46
+ #define CEREAL_DETAILS_POLYMORPHIC_IMPL_FWD_HPP_
47
+
48
+ namespace cereal
49
+ {
50
+ namespace detail
51
+ {
52
+ //! Forward declaration, see polymorphic_impl.hpp for more information
53
+ template <class Base, class Derived>
54
+ struct RegisterPolymorphicCaster;
55
+
56
+ //! Forward declaration, see polymorphic_impl.hpp for more information
57
+ struct PolymorphicCasters;
58
+
59
+ //! Forward declaration, see polymorphic_impl.hpp for more information
60
+ template <class Base, class Derived>
61
+ struct PolymorphicRelation;
62
+ } // namespace detail
63
+ } // namespace cereal
64
+
65
+ #endif // CEREAL_DETAILS_POLYMORPHIC_IMPL_FWD_HPP_
@@ -0,0 +1,127 @@
1
+ /*! \file static_object.hpp
2
+ \brief Internal polymorphism static object support
3
+ \ingroup Internal */
4
+ /*
5
+ Copyright (c) 2014, Randolph Voorhies, Shane Grant
6
+ All rights reserved.
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are met:
9
+ * Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ * Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+ * Neither the name of cereal nor the
15
+ names of its contributors may be used to endorse or promote products
16
+ derived from this software without specific prior written permission.
17
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
+ DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
21
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+ #ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_
29
+ #define CEREAL_DETAILS_STATIC_OBJECT_HPP_
30
+
31
+ #include "cereal/macros.hpp"
32
+
33
+ #if CEREAL_THREAD_SAFE
34
+ #include <mutex>
35
+ #endif
36
+
37
+ //! Prevent link optimization from removing non-referenced static objects
38
+ /*! Especially for polymorphic support, we create static objects which
39
+ may not ever be explicitly referenced. Most linkers will detect this
40
+ and remove the code causing various unpleasant runtime errors. These
41
+ macros, adopted from Boost (see force_include.hpp) prevent this
42
+ (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
43
+ Use, modification and distribution is subject to the Boost Software
44
+ License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
45
+ http://www.boost.org/LICENSE_1_0.txt) */
46
+
47
+ #ifdef _MSC_VER
48
+ # define CEREAL_DLL_EXPORT __declspec(dllexport)
49
+ # define CEREAL_USED
50
+ #else // clang or gcc
51
+ # define CEREAL_DLL_EXPORT __attribute__ ((visibility("default")))
52
+ # define CEREAL_USED __attribute__ ((__used__))
53
+ #endif
54
+
55
+ namespace cereal
56
+ {
57
+ namespace detail
58
+ {
59
+ //! A static, pre-execution object
60
+ /*! This class will create a single copy (singleton) of some
61
+ type and ensures that merely referencing this type will
62
+ cause it to be instantiated and initialized pre-execution.
63
+ For example, this is used heavily in the polymorphic pointer
64
+ serialization mechanisms to bind various archive types with
65
+ different polymorphic classes */
66
+ template <class T>
67
+ class CEREAL_DLL_EXPORT StaticObject
68
+ {
69
+ private:
70
+
71
+ static T & create()
72
+ {
73
+ static T t;
74
+ //! Forces instantiation at pre-execution time
75
+ (void)instance;
76
+ return t;
77
+ }
78
+
79
+ StaticObject( StaticObject const & /*other*/ ) {}
80
+
81
+ public:
82
+ static T & getInstance()
83
+ {
84
+ return create();
85
+ }
86
+
87
+ //! A class that acts like std::lock_guard
88
+ class LockGuard
89
+ {
90
+ #if CEREAL_THREAD_SAFE
91
+ public:
92
+ LockGuard(std::mutex & m) : lock(m) {}
93
+ private:
94
+ std::unique_lock<std::mutex> lock;
95
+ #else
96
+ public:
97
+ LockGuard(LockGuard const &) = default; // prevents implicit copy ctor warning
98
+ ~LockGuard() CEREAL_NOEXCEPT {} // prevents variable not used
99
+ #endif
100
+ };
101
+
102
+ //! Attempts to lock this static object for the current scope
103
+ /*! @note This function is a no-op if cereal is not compiled with
104
+ thread safety enabled (CEREAL_THREAD_SAFE = 1).
105
+
106
+ This function returns an object that holds a lock for
107
+ this StaticObject that will release its lock upon destruction. This
108
+ call will block until the lock is available. */
109
+ static LockGuard lock()
110
+ {
111
+ #if CEREAL_THREAD_SAFE
112
+ static std::mutex instanceMutex;
113
+ return LockGuard{instanceMutex};
114
+ #else
115
+ return LockGuard{};
116
+ #endif
117
+ }
118
+
119
+ private:
120
+ static T & instance;
121
+ };
122
+
123
+ template <class T> T & StaticObject<T>::instance = StaticObject<T>::create();
124
+ } // namespace detail
125
+ } // namespace cereal
126
+
127
+ #endif // CEREAL_DETAILS_STATIC_OBJECT_HPP_
@@ -0,0 +1,1411 @@
1
+ /*! \file traits.hpp
2
+ \brief Internal type trait support
3
+ \ingroup Internal */
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
+ // ######################################################################
55
+ //! Used to delay a static_assert until template instantiation
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
+
65
+ //! Return type for SFINAE Enablers
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
+
85
+ //! Used as the default value for EnableIf and DisableIf template parameters
86
+ /*! @relates EnableIf
87
+ @relates DisableIf */
88
+ static const detail::sfinae sfinae = {};
89
+
90
+ // ######################################################################
91
+ //! Provides a way to enable a function if conditions are met
92
+ /*! This is intended to be used in a near identical fashion to std::enable_if
93
+ while being significantly easier to read at the cost of not allowing for as
94
+ complicated of a condition.
95
+
96
+ This will compile (allow the function) if every condition evaluates to true.
97
+ at compile time. This should be used with SFINAE to ensure that at least
98
+ one other candidate function works when one fails due to an EnableIf.
99
+
100
+ This should be used as the las template parameter to a function as
101
+ an unnamed parameter with a default value of cereal::traits::sfinae:
102
+
103
+ @code{cpp}
104
+ // using by making the last template argument variadic
105
+ template <class T, EnableIf<std::is_same<T, bool>::value> = sfinae>
106
+ void func(T t );
107
+ @endcode
108
+
109
+ Note that this performs a logical AND of all conditions, so you will need
110
+ to construct more complicated requirements with this fact in mind.
111
+
112
+ @relates DisableIf
113
+ @relates sfinae
114
+ @tparam Conditions The conditions which will be logically ANDed to enable the function. */
115
+ template <bool ... Conditions>
116
+ using EnableIf = typename detail::EnableIfHelper<Conditions...>::type;
117
+
118
+ // ######################################################################
119
+ //! Provides a way to disable a function if conditions are met
120
+ /*! This is intended to be used in a near identical fashion to std::enable_if
121
+ while being significantly easier to read at the cost of not allowing for as
122
+ complicated of a condition.
123
+
124
+ This will compile (allow the function) if every condition evaluates to false.
125
+ This should be used with SFINAE to ensure that at least one other candidate
126
+ function works when one fails due to a DisableIf.
127
+
128
+ This should be used as the las template parameter to a function as
129
+ an unnamed parameter with a default value of cereal::traits::sfinae:
130
+
131
+ @code{cpp}
132
+ // using by making the last template argument variadic
133
+ template <class T, DisableIf<std::is_same<T, bool>::value> = sfinae>
134
+ void func(T t );
135
+ @endcode
136
+
137
+ This is often used in conjunction with EnableIf to form an enable/disable pair of
138
+ overloads.
139
+
140
+ Note that this performs a logical AND of all conditions, so you will need
141
+ to construct more complicated requirements with this fact in mind. If all conditions
142
+ hold, the function will be disabled.
143
+
144
+ @relates EnableIf
145
+ @relates sfinae
146
+ @tparam Conditions The conditions which will be logically ANDed to disable the function. */
147
+ template <bool ... Conditions>
148
+ using DisableIf = typename detail::DisableIfHelper<Conditions...>::type;
149
+
150
+ // ######################################################################
151
+ namespace detail
152
+ {
153
+ template <class InputArchive>
154
+ struct get_output_from_input : no
155
+ {
156
+ static_assert( detail::delay_static_assert<InputArchive>::value,
157
+ "Could not find an associated output archive for input archive." );
158
+ };
159
+
160
+ template <class OutputArchive>
161
+ struct get_input_from_output : no
162
+ {
163
+ static_assert( detail::delay_static_assert<OutputArchive>::value,
164
+ "Could not find an associated input archive for output archive." );
165
+ };
166
+ }
167
+
168
+ //! Sets up traits that relate an input archive to an output archive
169
+ #define CEREAL_SETUP_ARCHIVE_TRAITS(InputArchive, OutputArchive) \
170
+ namespace cereal { namespace traits { namespace detail { \
171
+ template <> struct get_output_from_input<InputArchive> \
172
+ { using type = OutputArchive; }; \
173
+ template <> struct get_input_from_output<OutputArchive> \
174
+ { using type = InputArchive; }; } } } /* end namespaces */
175
+
176
+ // ######################################################################
177
+ //! Used to convert a MAKE_HAS_XXX macro into a versioned variant
178
+ #define CEREAL_MAKE_VERSIONED_TEST ,0
179
+
180
+ // ######################################################################
181
+ //! Creates a test for whether a non const member function exists
182
+ /*! This creates a class derived from std::integral_constant that will be true if
183
+ the type has the proper member function for the given archive.
184
+
185
+ @param name The name of the function to test for (e.g. serialize, load, save)
186
+ @param test_name The name to give the test for the function being tested for (e.g. serialize, versioned_serialize)
187
+ @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
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
+ // ######################################################################
214
+ //! Creates a test for whether a non const non-member function exists
215
+ /*! This creates a class derived from std::integral_constant that will be true if
216
+ the type has the proper non-member function for the given archive. */
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
243
+ CEREAL_MAKE_HAS_NON_MEMBER_TEST(serialize, CEREAL_SERIALIZE_FUNCTION_NAME,);
244
+
245
+ // ######################################################################
246
+ // Non Member Serialize (versioned)
247
+ CEREAL_MAKE_HAS_NON_MEMBER_TEST(versioned_serialize, CEREAL_SERIALIZE_FUNCTION_NAME, CEREAL_MAKE_VERSIONED_TEST);
248
+
249
+ // ######################################################################
250
+ // Member Load
251
+ CEREAL_MAKE_HAS_MEMBER_TEST(load, load,);
252
+
253
+ // ######################################################################
254
+ // Member Load (versioned)
255
+ CEREAL_MAKE_HAS_MEMBER_TEST(load, versioned_load, CEREAL_MAKE_VERSIONED_TEST);
256
+
257
+ // ######################################################################
258
+ // Non Member Load
259
+ CEREAL_MAKE_HAS_NON_MEMBER_TEST(load, CEREAL_LOAD_FUNCTION_NAME,);
260
+
261
+ // ######################################################################
262
+ // Non Member Load (versioned)
263
+ CEREAL_MAKE_HAS_NON_MEMBER_TEST(versioned_load, CEREAL_LOAD_FUNCTION_NAME, CEREAL_MAKE_VERSIONED_TEST);
264
+
265
+ // ######################################################################
266
+ #undef CEREAL_MAKE_HAS_NON_MEMBER_TEST
267
+ #undef CEREAL_MAKE_HAS_MEMBER_TEST
268
+
269
+ // ######################################################################
270
+ //! Creates a test for whether a member save function exists
271
+ /*! This creates a class derived from std::integral_constant that will be true if
272
+ the type has the proper member function for the given archive.
273
+
274
+ @param test_name The name to give the test (e.g. save or versioned_save)
275
+ @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
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
324
+ CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(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)
337
+ CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(versioned_save, CEREAL_MAKE_VERSIONED_TEST)
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
+ // ######################################################################
352
+ //! Creates a test for whether a non-member save function exists
353
+ /*! This creates a class derived from std::integral_constant that will be true if
354
+ the type has the proper non-member function for the given archive.
355
+
356
+ @param test_name The name to give the test (e.g. save or versioned_save)
357
+ @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
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
391
+ CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(save, )
392
+
393
+ // ######################################################################
394
+ // Non Member Save (versioned)
395
+ CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(versioned_save, CEREAL_MAKE_VERSIONED_TEST)
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
+ // ######################################################################
417
+ //! Creates implementation details for whether a member save_minimal function exists
418
+ /*! This creates a class derived from std::integral_constant that will be true if
419
+ the type has the proper member function for the given archive.
420
+
421
+ @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal)
422
+ @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
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
+ // ######################################################################
475
+ //! Creates helpers for minimal save functions
476
+ /*! The get_member_*_type structs allow access to the return type of a save_minimal,
477
+ assuming that the function actually exists. If the function does not
478
+ exist, the type will be void.
479
+
480
+ @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal)
481
+ @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
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
+ // ######################################################################
497
+ //! Creates a test for whether a member save_minimal function exists
498
+ /*! This creates a class derived from std::integral_constant that will be true if
499
+ the type has the proper member function for the given archive.
500
+
501
+ @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal) */
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
519
+ CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(save_minimal, )
520
+ CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(save_minimal, )
521
+ CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(save_minimal)
522
+
523
+ // ######################################################################
524
+ // Member Save Minimal (versioned)
525
+ CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
526
+ CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
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
+ // ######################################################################
535
+ //! Creates a test for whether a non-member save_minimal function exists
536
+ /*! This creates a class derived from std::integral_constant that will be true if
537
+ the type has the proper member function for the given archive.
538
+
539
+ @param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal)
540
+ @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
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
591
+ CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(save_minimal, )
592
+
593
+ // ######################################################################
594
+ // Non-Member Save Minimal (versioned)
595
+ CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
596
+
597
+ // ######################################################################
598
+ #undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST
599
+
600
+ // ######################################################################
601
+ // Load Minimal Utilities
602
+ namespace detail
603
+ {
604
+ //! Used to help strip away conversion wrappers
605
+ /*! If someone writes a non-member load/save minimal function that accepts its
606
+ parameter as some generic template type and needs to perform trait checks
607
+ on that type, our NoConvert wrappers will interfere with this. Using
608
+ the struct strip_minmal, users can strip away our wrappers to get to
609
+ the underlying type, allowing traits to work properly */
610
+ struct NoConvertBase {};
611
+
612
+ //! A struct that prevents implicit conversion
613
+ /*! Any type instantiated with this struct will be unable to implicitly convert
614
+ to another type. Is designed to only allow conversion to Source const &.
615
+
616
+ @tparam Source the type of the original source */
617
+ template <class Source>
618
+ struct NoConvertConstRef : NoConvertBase
619
+ {
620
+ using type = Source; //!< Used to get underlying type easily
621
+
622
+ template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
623
+ operator Dest () = delete;
624
+
625
+ //! only allow conversion if the types are the same and we are converting into a const reference
626
+ template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
627
+ operator Dest const & ();
628
+ };
629
+
630
+ //! A struct that prevents implicit conversion
631
+ /*! Any type instantiated with this struct will be unable to implicitly convert
632
+ to another type. Is designed to only allow conversion to Source &.
633
+
634
+ @tparam Source the type of the original source */
635
+ template <class Source>
636
+ struct NoConvertRef : NoConvertBase
637
+ {
638
+ using type = Source; //!< Used to get underlying type easily
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
+
648
+ //! only allow conversion if the types are the same and we are converting into a const reference
649
+ template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type>
650
+ operator Dest & ();
651
+ };
652
+
653
+ //! A type that can implicitly convert to anything else
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
+ // ######################################################################
665
+ //! Creates a test for whether a member load_minimal function exists
666
+ /*! This creates a class derived from std::integral_constant that will be true if
667
+ the type has the proper member function for the given archive.
668
+
669
+ Our strategy here is to first check if a function matching the signature more or less exists
670
+ (allow anything like load_minimal(xxx) using AnyConvert, and then secondly enforce
671
+ that it has the correct signature using NoConvertConstRef
672
+
673
+ @param test_name The name to give the test (e.g. load_minimal or versioned_load_minimal)
674
+ @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
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
+ // ######################################################################
720
+ //! Creates helpers for minimal load functions
721
+ /*! The has_member_*_wrapper structs ensure that the load and save types for the
722
+ requested function type match appropriately.
723
+
724
+ @param load_test_name The name to give the test (e.g. load_minimal or versioned_load_minimal)
725
+ @param save_test_name The name to give the test (e.g. save_minimal or versioned_save_minimal,
726
+ should match the load name.
727
+ @param save_test_prefix The name to give the test (e.g. save_minimal or versioned_save_minimal,
728
+ should match the load name, without the trailing "_minimal" (e.g.
729
+ save or versioned_save). Needed because the preprocessor is an abomination.
730
+ @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
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
+ // ######################################################################
758
+ //! Creates a test for whether a member load_minimal function exists
759
+ /*! This creates a class derived from std::integral_constant that will be true if
760
+ the type has the proper member function for the given archive.
761
+
762
+ @param load_test_name The name to give the test (e.g. load_minimal or versioned_load_minimal)
763
+ @param load_test_prefix The above parameter minus the trailing "_minimal" */
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
771
+ CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(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)
777
+ CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(versioned_load_minimal, CEREAL_MAKE_VERSIONED_TEST)
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
792
+ void CEREAL_SAVE_MINIMAL_FUNCTION_NAME();
793
+ #endif // CEREAL_OLDER_GCC
794
+ } // namespace detail
795
+
796
+ // ######################################################################
797
+ //! Creates a test for whether a non-member load_minimal function exists
798
+ /*! This creates a class derived from std::integral_constant that will be true if
799
+ the type has the proper member function for the given archive.
800
+
801
+ See notes from member load_minimal implementation.
802
+
803
+ Note that there should be an additional const check on load_minimal after the valid check,
804
+ but this currently interferes with many valid uses of minimal serialization. It has been
805
+ removed (see #565 on github) and previously was:
806
+
807
+ @code
808
+ static_assert( check::const_valid || !check::exists,
809
+ "cereal detected an invalid serialization type parameter in non-member " #test_name ". "
810
+ #test_name " non-member functions must accept their serialization type by non-const reference" );
811
+ @endcode
812
+
813
+ See #132, #436, #263, and #565 on https://github.com/USCiLab/cereal for more details.
814
+
815
+ @param test_name The name to give the test (e.g. load_minimal or versioned_load_minimal)
816
+ @param save_name The corresponding name the save test would have (e.g. save_minimal or versioned_save_minimal)
817
+ @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
818
+ #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned) \
819
+ namespace detail \
820
+ { \
821
+ template <class T, class A, class U = void> \
822
+ struct has_non_member_##test_name##_impl \
823
+ { \
824
+ template <class TT, class AA> \
825
+ static auto test(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
826
+ std::declval<AA const &>(), std::declval<TT&>(), AnyConvert() versioned ), yes() ); \
827
+ template <class, class> static no test( ... ); \
828
+ static const bool exists = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \
829
+ \
830
+ template <class TT, class AA, class UU> \
831
+ static auto test2(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
832
+ std::declval<AA const &>(), std::declval<TT&>(), NoConvertConstRef<UU>() versioned ), yes() ); \
833
+ template <class, class, class> static no test2( ... ); \
834
+ static const bool valid = std::is_same<decltype( test2<T, A, U>( 0 ) ), yes>::value; \
835
+ \
836
+ template <class TT, class AA> \
837
+ static auto test3(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \
838
+ std::declval<AA const &>(), NoConvertRef<TT>(), AnyConvert() versioned ), yes() ); \
839
+ template <class, class> static no test3( ... ); \
840
+ static const bool const_valid = std::is_same<decltype( test3<T, A>( 0 ) ), yes>::value; \
841
+ }; \
842
+ \
843
+ template <class T, class A, bool Valid> \
844
+ struct has_non_member_##test_name##_wrapper : std::false_type {}; \
845
+ \
846
+ template <class T, class A> \
847
+ struct has_non_member_##test_name##_wrapper<T, A, true> \
848
+ { \
849
+ using AOut = typename detail::get_output_from_input<A>::type; \
850
+ \
851
+ static_assert( detail::has_non_member_##save_name##_impl<T, AOut>::valid, \
852
+ "cereal detected non-member " #test_name " but no valid non-member " #save_name ". \n " \
853
+ "cannot evaluate correctness of " #test_name " without valid " #save_name "." ); \
854
+ \
855
+ using SaveType = typename detail::get_non_member_##save_name##_type<T, AOut, true>::type; \
856
+ using check = has_non_member_##test_name##_impl<T, A, SaveType>; \
857
+ static const bool value = check::exists; \
858
+ \
859
+ static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member " \
860
+ #test_name " and " #save_name " functions. \n " \
861
+ "the paramater to " #test_name " must be a constant reference to the type that " #save_name " returns." ); \
862
+ }; \
863
+ } /* namespace detail */ \
864
+ \
865
+ template <class T, class A> \
866
+ struct has_non_member_##test_name : std::integral_constant<bool, \
867
+ detail::has_non_member_##test_name##_wrapper<T, A, detail::has_non_member_##test_name##_impl<T, A>::exists>::value> {};
868
+
869
+ // ######################################################################
870
+ // Non-Member Load Minimal
871
+ CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(load_minimal, save_minimal, )
872
+
873
+ // ######################################################################
874
+ // Non-Member Load Minimal (versioned)
875
+ CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST)
876
+
877
+ // ######################################################################
878
+ #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST
879
+
880
+ // ######################################################################
881
+ namespace detail
882
+ {
883
+ // const stripped away before reaching here, prevents errors on conversion from
884
+ // construct<const T> to construct<T>
885
+ template<typename T, typename A>
886
+ struct has_member_load_and_construct_impl : std::integral_constant<bool,
887
+ std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
888
+ { };
889
+
890
+ template<typename T, typename A>
891
+ struct has_member_versioned_load_and_construct_impl : std::integral_constant<bool,
892
+ std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>(), 0 ) ), void>::value>
893
+ { };
894
+ } // namespace detail
895
+
896
+ //! Member load and construct check
897
+ template<typename T, typename A>
898
+ struct has_member_load_and_construct : detail::has_member_load_and_construct_impl<typename std::remove_const<T>::type, A>
899
+ { };
900
+
901
+ //! Member load and construct check (versioned)
902
+ template<typename T, typename A>
903
+ struct has_member_versioned_load_and_construct : detail::has_member_versioned_load_and_construct_impl<typename std::remove_const<T>::type, A>
904
+ { };
905
+
906
+ // ######################################################################
907
+ //! Creates a test for whether a non-member load_and_construct specialization exists
908
+ /*! This creates a class derived from std::integral_constant that will be true if
909
+ the type has the proper non-member function for the given archive. */
910
+ #define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(test_name, versioned) \
911
+ namespace detail \
912
+ { \
913
+ template <class T, class A> \
914
+ struct has_non_member_##test_name##_impl \
915
+ { \
916
+ template <class TT, class AA> \
917
+ static auto test(int) -> decltype( LoadAndConstruct<TT>::load_and_construct( \
918
+ std::declval<AA&>(), std::declval< ::cereal::construct<TT>&>() versioned ), yes()); \
919
+ template <class, class> \
920
+ static no test( ... ); \
921
+ static const bool value = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \
922
+ }; \
923
+ } /* end namespace detail */ \
924
+ template <class T, class A> \
925
+ struct has_non_member_##test_name : \
926
+ std::integral_constant<bool, detail::has_non_member_##test_name##_impl<typename std::remove_const<T>::type, A>::value> {};
927
+
928
+ // ######################################################################
929
+ //! Non member load and construct check
930
+ CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(load_and_construct, )
931
+
932
+ // ######################################################################
933
+ //! Non member load and construct check (versioned)
934
+ CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST(versioned_load_and_construct, CEREAL_MAKE_VERSIONED_TEST)
935
+
936
+ // ######################################################################
937
+ //! Has either a member or non member load and construct
938
+ template<typename T, typename A>
939
+ struct has_load_and_construct : std::integral_constant<bool,
940
+ has_member_load_and_construct<T, A>::value || has_non_member_load_and_construct<T, A>::value ||
941
+ has_member_versioned_load_and_construct<T, A>::value || has_non_member_versioned_load_and_construct<T, A>::value>
942
+ { };
943
+
944
+ // ######################################################################
945
+ #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_AND_CONSTRUCT_TEST
946
+
947
+ // ######################################################################
948
+ // End of serialization existence tests
949
+ #undef CEREAL_MAKE_VERSIONED_TEST
950
+
951
+ // ######################################################################
952
+ template <class T, class InputArchive, class OutputArchive>
953
+ struct has_member_split : std::integral_constant<bool,
954
+ (has_member_load<T, InputArchive>::value && has_member_save<T, OutputArchive>::value) ||
955
+ (has_member_versioned_load<T, InputArchive>::value && has_member_versioned_save<T, OutputArchive>::value)> {};
956
+
957
+ // ######################################################################
958
+ template <class T, class InputArchive, class OutputArchive>
959
+ struct has_non_member_split : std::integral_constant<bool,
960
+ (has_non_member_load<T, InputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
961
+ (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_versioned_save<T, OutputArchive>::value)> {};
962
+
963
+ // ######################################################################
964
+ template <class T, class OutputArchive>
965
+ struct has_invalid_output_versioning : std::integral_constant<bool,
966
+ (has_member_versioned_save<T, OutputArchive>::value && has_member_save<T, OutputArchive>::value) ||
967
+ (has_non_member_versioned_save<T, OutputArchive>::value && has_non_member_save<T, OutputArchive>::value) ||
968
+ (has_member_versioned_serialize<T, OutputArchive>::value && has_member_serialize<T, OutputArchive>::value) ||
969
+ (has_non_member_versioned_serialize<T, OutputArchive>::value && has_non_member_serialize<T, OutputArchive>::value) ||
970
+ (has_member_versioned_save_minimal<T, OutputArchive>::value && has_member_save_minimal<T, OutputArchive>::value) ||
971
+ (has_non_member_versioned_save_minimal<T, OutputArchive>::value && has_non_member_save_minimal<T, OutputArchive>::value)> {};
972
+
973
+ // ######################################################################
974
+ template <class T, class InputArchive>
975
+ struct has_invalid_input_versioning : std::integral_constant<bool,
976
+ (has_member_versioned_load<T, InputArchive>::value && has_member_load<T, InputArchive>::value) ||
977
+ (has_non_member_versioned_load<T, InputArchive>::value && has_non_member_load<T, InputArchive>::value) ||
978
+ (has_member_versioned_serialize<T, InputArchive>::value && has_member_serialize<T, InputArchive>::value) ||
979
+ (has_non_member_versioned_serialize<T, InputArchive>::value && has_non_member_serialize<T, InputArchive>::value) ||
980
+ (has_member_versioned_load_minimal<T, InputArchive>::value && has_member_load_minimal<T, InputArchive>::value) ||
981
+ (has_non_member_versioned_load_minimal<T, InputArchive>::value && has_non_member_load_minimal<T, InputArchive>::value)> {};
982
+
983
+ // ######################################################################
984
+ namespace detail
985
+ {
986
+ //! Create a test for a cereal::specialization entry
987
+ #define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name) \
988
+ template <class T, class A> \
989
+ struct is_specialized_##name : std::integral_constant<bool, \
990
+ !std::is_base_of<std::false_type, specialize<A, T, specialization::name>>::value> {}
991
+
992
+ CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_serialize);
993
+ CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save);
994
+ CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save_minimal);
995
+ CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_serialize);
996
+ CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save);
997
+ CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save_minimal);
998
+
999
+ #undef CEREAL_MAKE_IS_SPECIALIZED_IMPL
1000
+
1001
+ //! Number of specializations detected
1002
+ template <class T, class A>
1003
+ struct count_specializations : std::integral_constant<int,
1004
+ is_specialized_member_serialize<T, A>::value +
1005
+ is_specialized_member_load_save<T, A>::value +
1006
+ is_specialized_member_load_save_minimal<T, A>::value +
1007
+ is_specialized_non_member_serialize<T, A>::value +
1008
+ is_specialized_non_member_load_save<T, A>::value +
1009
+ is_specialized_non_member_load_save_minimal<T, A>::value> {};
1010
+ } // namespace detail
1011
+
1012
+ //! Check if any specialization exists for a type
1013
+ template <class T, class A>
1014
+ struct is_specialized : std::integral_constant<bool,
1015
+ detail::is_specialized_member_serialize<T, A>::value ||
1016
+ detail::is_specialized_member_load_save<T, A>::value ||
1017
+ detail::is_specialized_member_load_save_minimal<T, A>::value ||
1018
+ detail::is_specialized_non_member_serialize<T, A>::value ||
1019
+ detail::is_specialized_non_member_load_save<T, A>::value ||
1020
+ detail::is_specialized_non_member_load_save_minimal<T, A>::value>
1021
+ {
1022
+ static_assert(detail::count_specializations<T, A>::value <= 1, "More than one explicit specialization detected for type.");
1023
+ };
1024
+
1025
+ //! Create the static assertion for some specialization
1026
+ /*! This assertion will fail if the type is indeed specialized and does not have the appropriate
1027
+ type of serialization functions */
1028
+ #define CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, print_name, spec_name) \
1029
+ static_assert( (is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value && \
1030
+ (has_##name<T, A>::value || has_##versioned_name<T, A>::value)) \
1031
+ || !(is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value), \
1032
+ "cereal detected " #print_name " specialization but no " #print_name " serialize function" )
1033
+
1034
+ //! Generates a test for specialization for versioned and unversioned functions
1035
+ /*! This creates checks that can be queried to see if a given type of serialization function
1036
+ has been specialized for this type */
1037
+ #define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name) \
1038
+ template <class T, class A> \
1039
+ struct is_specialized_##name : std::integral_constant<bool, \
1040
+ is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \
1041
+ { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, name, spec_name); }; \
1042
+ template <class T, class A> \
1043
+ struct is_specialized_##versioned_name : std::integral_constant<bool, \
1044
+ is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \
1045
+ { CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, versioned_name, spec_name); }
1046
+
1047
+ CEREAL_MAKE_IS_SPECIALIZED(member_serialize, member_versioned_serialize, member_serialize);
1048
+ CEREAL_MAKE_IS_SPECIALIZED(non_member_serialize, non_member_versioned_serialize, non_member_serialize);
1049
+
1050
+ CEREAL_MAKE_IS_SPECIALIZED(member_save, member_versioned_save, member_load_save);
1051
+ CEREAL_MAKE_IS_SPECIALIZED(non_member_save, non_member_versioned_save, non_member_load_save);
1052
+ CEREAL_MAKE_IS_SPECIALIZED(member_load, member_versioned_load, member_load_save);
1053
+ CEREAL_MAKE_IS_SPECIALIZED(non_member_load, non_member_versioned_load, non_member_load_save);
1054
+
1055
+ CEREAL_MAKE_IS_SPECIALIZED(member_save_minimal, member_versioned_save_minimal, member_load_save_minimal);
1056
+ CEREAL_MAKE_IS_SPECIALIZED(non_member_save_minimal, non_member_versioned_save_minimal, non_member_load_save_minimal);
1057
+ CEREAL_MAKE_IS_SPECIALIZED(member_load_minimal, member_versioned_load_minimal, member_load_save_minimal);
1058
+ CEREAL_MAKE_IS_SPECIALIZED(non_member_load_minimal, non_member_versioned_load_minimal, non_member_load_save_minimal);
1059
+
1060
+ #undef CEREAL_MAKE_IS_SPECIALIZED_ASSERT
1061
+ #undef CEREAL_MAKE_IS_SPECIALIZED
1062
+
1063
+ // ######################################################################
1064
+ // detects if a type has any active minimal output serialization
1065
+ template <class T, class OutputArchive>
1066
+ struct has_minimal_output_serialization : std::integral_constant<bool,
1067
+ is_specialized_member_save_minimal<T, OutputArchive>::value ||
1068
+ ((has_member_save_minimal<T, OutputArchive>::value ||
1069
+ has_non_member_save_minimal<T, OutputArchive>::value ||
1070
+ has_member_versioned_save_minimal<T, OutputArchive>::value ||
1071
+ has_non_member_versioned_save_minimal<T, OutputArchive>::value) &&
1072
+ !(is_specialized_member_serialize<T, OutputArchive>::value ||
1073
+ is_specialized_member_save<T, OutputArchive>::value))> {};
1074
+
1075
+ // ######################################################################
1076
+ // detects if a type has any active minimal input serialization
1077
+ template <class T, class InputArchive>
1078
+ struct has_minimal_input_serialization : std::integral_constant<bool,
1079
+ is_specialized_member_load_minimal<T, InputArchive>::value ||
1080
+ ((has_member_load_minimal<T, InputArchive>::value ||
1081
+ has_non_member_load_minimal<T, InputArchive>::value ||
1082
+ has_member_versioned_load_minimal<T, InputArchive>::value ||
1083
+ has_non_member_versioned_load_minimal<T, InputArchive>::value) &&
1084
+ !(is_specialized_member_serialize<T, InputArchive>::value ||
1085
+ is_specialized_member_load<T, InputArchive>::value))> {};
1086
+
1087
+ // ######################################################################
1088
+ namespace detail
1089
+ {
1090
+ //! The number of output serialization functions available
1091
+ /*! If specialization is being used, we'll count only those; otherwise we'll count everything */
1092
+ template <class T, class OutputArchive>
1093
+ struct count_output_serializers : std::integral_constant<int,
1094
+ count_specializations<T, OutputArchive>::value ? count_specializations<T, OutputArchive>::value :
1095
+ has_member_save<T, OutputArchive>::value +
1096
+ has_non_member_save<T, OutputArchive>::value +
1097
+ has_member_serialize<T, OutputArchive>::value +
1098
+ has_non_member_serialize<T, OutputArchive>::value +
1099
+ has_member_save_minimal<T, OutputArchive>::value +
1100
+ has_non_member_save_minimal<T, OutputArchive>::value +
1101
+ /*-versioned---------------------------------------------------------*/
1102
+ has_member_versioned_save<T, OutputArchive>::value +
1103
+ has_non_member_versioned_save<T, OutputArchive>::value +
1104
+ has_member_versioned_serialize<T, OutputArchive>::value +
1105
+ has_non_member_versioned_serialize<T, OutputArchive>::value +
1106
+ has_member_versioned_save_minimal<T, OutputArchive>::value +
1107
+ has_non_member_versioned_save_minimal<T, OutputArchive>::value> {};
1108
+ }
1109
+
1110
+ template <class T, class OutputArchive>
1111
+ struct is_output_serializable : std::integral_constant<bool,
1112
+ detail::count_output_serializers<T, OutputArchive>::value == 1> {};
1113
+
1114
+ // ######################################################################
1115
+ namespace detail
1116
+ {
1117
+ //! The number of input serialization functions available
1118
+ /*! If specialization is being used, we'll count only those; otherwise we'll count everything */
1119
+ template <class T, class InputArchive>
1120
+ struct count_input_serializers : std::integral_constant<int,
1121
+ count_specializations<T, InputArchive>::value ? count_specializations<T, InputArchive>::value :
1122
+ has_member_load<T, InputArchive>::value +
1123
+ has_non_member_load<T, InputArchive>::value +
1124
+ has_member_serialize<T, InputArchive>::value +
1125
+ has_non_member_serialize<T, InputArchive>::value +
1126
+ has_member_load_minimal<T, InputArchive>::value +
1127
+ has_non_member_load_minimal<T, InputArchive>::value +
1128
+ /*-versioned---------------------------------------------------------*/
1129
+ has_member_versioned_load<T, InputArchive>::value +
1130
+ has_non_member_versioned_load<T, InputArchive>::value +
1131
+ has_member_versioned_serialize<T, InputArchive>::value +
1132
+ has_non_member_versioned_serialize<T, InputArchive>::value +
1133
+ has_member_versioned_load_minimal<T, InputArchive>::value +
1134
+ has_non_member_versioned_load_minimal<T, InputArchive>::value> {};
1135
+ }
1136
+
1137
+ template <class T, class InputArchive>
1138
+ struct is_input_serializable : std::integral_constant<bool,
1139
+ detail::count_input_serializers<T, InputArchive>::value == 1> {};
1140
+
1141
+ // ######################################################################
1142
+ // Base Class Support
1143
+ namespace detail
1144
+ {
1145
+ struct base_class_id
1146
+ {
1147
+ template<class T>
1148
+ base_class_id(T const * const t) :
1149
+ type(typeid(T)),
1150
+ ptr(t),
1151
+ hash(std::hash<std::type_index>()(typeid(T)) ^ (std::hash<void const *>()(t) << 1))
1152
+ { }
1153
+
1154
+ bool operator==(base_class_id const & other) const
1155
+ { return (type == other.type) && (ptr == other.ptr); }
1156
+
1157
+ std::type_index type;
1158
+ void const * ptr;
1159
+ size_t hash;
1160
+ };
1161
+ struct base_class_id_hash { size_t operator()(base_class_id const & id) const { return id.hash; } };
1162
+ } // namespace detail
1163
+
1164
+ namespace detail
1165
+ {
1166
+ //! Common base type for base class casting
1167
+ struct BaseCastBase {};
1168
+
1169
+ template <class>
1170
+ struct get_base_class;
1171
+
1172
+ template <template<typename> class Cast, class Base>
1173
+ struct get_base_class<Cast<Base>>
1174
+ {
1175
+ using type = Base;
1176
+ };
1177
+
1178
+ //! Base class cast, behave as the test
1179
+ template <class Cast, template<class, class> class Test, class Archive,
1180
+ bool IsBaseCast = std::is_base_of<BaseCastBase, Cast>::value>
1181
+ struct has_minimal_base_class_serialization_impl : Test<typename get_base_class<Cast>::type, Archive>
1182
+ { };
1183
+
1184
+ //! Not a base class cast
1185
+ template <class Cast, template<class, class> class Test, class Archive>
1186
+ struct has_minimal_base_class_serialization_impl<Cast,Test, Archive, false> : std::false_type
1187
+ { };
1188
+ }
1189
+
1190
+ //! Checks to see if the base class used in a cast has a minimal serialization
1191
+ /*! @tparam Cast Either base_class or virtual_base_class wrapped type
1192
+ @tparam Test A has_minimal test (for either input or output)
1193
+ @tparam Archive The archive to use with the test */
1194
+ template <class Cast, template<class, class> class Test, class Archive>
1195
+ struct has_minimal_base_class_serialization : detail::has_minimal_base_class_serialization_impl<Cast, Test, Archive>
1196
+ { };
1197
+
1198
+
1199
+ // ######################################################################
1200
+ namespace detail
1201
+ {
1202
+ struct shared_from_this_wrapper
1203
+ {
1204
+ template <class U>
1205
+ static auto (check)( U const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() );
1206
+
1207
+ static auto (check)( ... ) -> decltype( std::false_type() );
1208
+
1209
+ template <class U>
1210
+ static auto get( U const & t ) -> decltype( t.shared_from_this() );
1211
+ };
1212
+ }
1213
+
1214
+ //! Determine if T or any base class of T has inherited from std::enable_shared_from_this
1215
+ template<class T>
1216
+ struct has_shared_from_this : decltype((detail::shared_from_this_wrapper::check)(std::declval<T>()))
1217
+ { };
1218
+
1219
+ //! Get the type of the base class of T which inherited from std::enable_shared_from_this
1220
+ template <class T>
1221
+ struct get_shared_from_this_base
1222
+ {
1223
+ private:
1224
+ using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>()));
1225
+ public:
1226
+ //! The type of the base of T that inherited from std::enable_shared_from_this
1227
+ using type = typename std::decay<typename PtrType::element_type>::type;
1228
+ };
1229
+
1230
+ // ######################################################################
1231
+ //! Extracts the true type from something possibly wrapped in a cereal NoConvert
1232
+ /*! Internally cereal uses some wrapper classes to test the validity of non-member
1233
+ minimal load and save functions. This can interfere with user type traits on
1234
+ templated load and save minimal functions. To get to the correct underlying type,
1235
+ users should use strip_minimal when performing any enable_if type type trait checks.
1236
+
1237
+ See the enum serialization in types/common.hpp for an example of using this */
1238
+ template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value>
1239
+ struct strip_minimal
1240
+ {
1241
+ using type = T;
1242
+ };
1243
+
1244
+ //! Specialization for types wrapped in a NoConvert
1245
+ template <class T>
1246
+ struct strip_minimal<T, true>
1247
+ {
1248
+ using type = typename T::type;
1249
+ };
1250
+
1251
+ // ######################################################################
1252
+ //! Determines whether the class T can be default constructed by cereal::access
1253
+ template <class T>
1254
+ struct is_default_constructible
1255
+ {
1256
+ #ifdef CEREAL_OLDER_GCC
1257
+ template <class TT, class SFINAE = void>
1258
+ struct test : no {};
1259
+ template <class TT>
1260
+ struct test<TT, typename detail::Void< decltype( cereal::access::construct<TT>() ) >::type> : yes {};
1261
+ static const bool value = test<T>();
1262
+ #else // NOT CEREAL_OLDER_GCC =========================================
1263
+ template <class TT>
1264
+ static auto test(int) -> decltype( cereal::access::construct<TT>(), yes());
1265
+ template <class>
1266
+ static no test(...);
1267
+ static const bool value = std::is_same<decltype(test<T>(0)), yes>::value;
1268
+ #endif // NOT CEREAL_OLDER_GCC
1269
+ };
1270
+
1271
+ // ######################################################################
1272
+ namespace detail
1273
+ {
1274
+ //! Removes all qualifiers and minimal wrappers from an archive
1275
+ template <class A>
1276
+ using decay_archive = typename std::decay<typename strip_minimal<A>::type>::type;
1277
+ }
1278
+
1279
+ //! Checks if the provided archive type is equal to some cereal archive type
1280
+ /*! This automatically does things such as std::decay and removing any other wrappers that may be
1281
+ on the Archive template parameter.
1282
+
1283
+ Example use:
1284
+ @code{cpp}
1285
+ // example use to disable a serialization function
1286
+ template <class Archive, EnableIf<cereal::traits::is_same_archive<Archive, cereal::BinaryOutputArchive>::value> = sfinae>
1287
+ void save( Archive & ar, MyType const & mt );
1288
+ @endcode */
1289
+ template <class ArchiveT, class CerealArchiveT>
1290
+ struct is_same_archive : std::integral_constant<bool,
1291
+ std::is_same<detail::decay_archive<ArchiveT>, CerealArchiveT>::value>
1292
+ { };
1293
+
1294
+ // ######################################################################
1295
+ //! A macro to use to restrict which types of archives your function will work for.
1296
+ /*! This requires you to have a template class parameter named Archive and replaces the void return
1297
+ type for your function.
1298
+
1299
+ INTYPE refers to the input archive type you wish to restrict on.
1300
+ OUTTYPE refers to the output archive type you wish to restrict on.
1301
+
1302
+ For example, if we want to limit a serialize to only work with binary serialization:
1303
+
1304
+ @code{.cpp}
1305
+ template <class Archive>
1306
+ CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
1307
+ serialize( Archive & ar, MyCoolType & m )
1308
+ {
1309
+ ar & m;
1310
+ }
1311
+ @endcode
1312
+
1313
+ If you need to do more restrictions in your enable_if, you will need to do this by hand.
1314
+ */
1315
+ #define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \
1316
+ typename std::enable_if<cereal::traits::is_same_archive<Archive, INTYPE>::value || cereal::traits::is_same_archive<Archive, OUTTYPE>::value, void>::type
1317
+
1318
+ //! Type traits only struct used to mark an archive as human readable (text based)
1319
+ /*! Archives that wish to identify as text based/human readable should inherit from
1320
+ this struct */
1321
+ struct TextArchive {};
1322
+
1323
+ //! Checks if an archive is a text archive (human readable)
1324
+ template <class A>
1325
+ struct is_text_archive : std::integral_constant<bool,
1326
+ std::is_base_of<TextArchive, detail::decay_archive<A>>::value>
1327
+ { };
1328
+ } // namespace traits
1329
+
1330
+ // ######################################################################
1331
+ namespace detail
1332
+ {
1333
+ template <class T, class A,
1334
+ bool Member = traits::has_member_load_and_construct<T, A>::value,
1335
+ bool MemberVersioned = traits::has_member_versioned_load_and_construct<T, A>::value,
1336
+ bool NonMember = traits::has_non_member_load_and_construct<T, A>::value,
1337
+ bool NonMemberVersioned = traits::has_non_member_versioned_load_and_construct<T, A>::value>
1338
+ struct Construct
1339
+ {
1340
+ static_assert( cereal::traits::detail::delay_static_assert<T>::value,
1341
+ "cereal found more than one compatible load_and_construct function for the provided type and archive combination. \n\n "
1342
+ "Types must either have a member load_and_construct function or a non-member specialization of LoadAndConstruct (you may not mix these). \n "
1343
+ "In addition, you may not mix versioned with non-versioned load_and_construct functions. \n\n " );
1344
+ static T * load_andor_construct( A & /*ar*/, construct<T> & /*construct*/ )
1345
+ { return nullptr; }
1346
+ };
1347
+
1348
+ // no load and construct case
1349
+ template <class T, class A>
1350
+ struct Construct<T, A, false, false, false, false>
1351
+ {
1352
+ static_assert( ::cereal::traits::is_default_constructible<T>::value,
1353
+ "Trying to serialize a an object with no default constructor. \n\n "
1354
+ "Types must either be default constructible or define either a member or non member Construct function. \n "
1355
+ "Construct functions generally have the signature: \n\n "
1356
+ "template <class Archive> \n "
1357
+ "static void load_and_construct(Archive & ar, cereal::construct<T> & construct) \n "
1358
+ "{ \n "
1359
+ " var a; \n "
1360
+ " ar( a ) \n "
1361
+ " construct( a ); \n "
1362
+ "} \n\n" );
1363
+ static T * load_andor_construct()
1364
+ { return ::cereal::access::construct<T>(); }
1365
+ };
1366
+
1367
+ // member non-versioned
1368
+ template <class T, class A>
1369
+ struct Construct<T, A, true, false, false, false>
1370
+ {
1371
+ static void load_andor_construct( A & ar, construct<T> & construct )
1372
+ {
1373
+ access::load_and_construct<T>( ar, construct );
1374
+ }
1375
+ };
1376
+
1377
+ // member versioned
1378
+ template <class T, class A>
1379
+ struct Construct<T, A, false, true, false, false>
1380
+ {
1381
+ static void load_andor_construct( A & ar, construct<T> & construct )
1382
+ {
1383
+ const auto version = ar.template loadClassVersion<T>();
1384
+ access::load_and_construct<T>( ar, construct, version );
1385
+ }
1386
+ };
1387
+
1388
+ // non-member non-versioned
1389
+ template <class T, class A>
1390
+ struct Construct<T, A, false, false, true, false>
1391
+ {
1392
+ static void load_andor_construct( A & ar, construct<T> & construct )
1393
+ {
1394
+ LoadAndConstruct<T>::load_and_construct( ar, construct );
1395
+ }
1396
+ };
1397
+
1398
+ // non-member versioned
1399
+ template <class T, class A>
1400
+ struct Construct<T, A, false, false, false, true>
1401
+ {
1402
+ static void load_andor_construct( A & ar, construct<T> & construct )
1403
+ {
1404
+ const auto version = ar.template loadClassVersion<T>();
1405
+ LoadAndConstruct<T>::load_and_construct( ar, construct, version );
1406
+ }
1407
+ };
1408
+ } // namespace detail
1409
+ } // namespace cereal
1410
+
1411
+ #endif // CEREAL_DETAILS_TRAITS_HPP_