| 7a956470 |
sago007 |
2016-02-14 17:09 |
1 |
/*! \file traits.hpp |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
2 |
\brief Internal type trait support |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
3 |
\ingroup Internal */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
4 |
/* |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
5 |
Copyright (c) 2014, Randolph Voorhies, Shane Grant |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
6 |
All rights reserved. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
7 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
8 |
Redistribution and use in source and binary forms, with or without |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
9 |
modification, are permitted provided that the following conditions are met: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
10 |
* Redistributions of source code must retain the above copyright |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
11 |
notice, this list of conditions and the following disclaimer. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
12 |
* Redistributions in binary form must reproduce the above copyright |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
13 |
notice, this list of conditions and the following disclaimer in the |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
14 |
documentation and/or other materials provided with the distribution. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
15 |
* Neither the name of cereal nor the |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
16 |
names of its contributors may be used to endorse or promote products |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
17 |
derived from this software without specific prior written permission. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
18 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
19 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
20 |
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
21 |
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
22 |
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
23 |
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
24 |
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
25 |
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
26 |
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
27 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
28 |
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
29 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
30 |
#ifndef CEREAL_DETAILS_TRAITS_HPP_ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
31 |
#define CEREAL_DETAILS_TRAITS_HPP_ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
32 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
33 |
#ifndef __clang__ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
34 |
#if (__GNUC__ == 4 && __GNUC_MINOR__ <= 7) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
35 |
#define CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
36 |
#endif // gcc 4.7 or earlier |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
37 |
#endif // __clang__ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
38 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
39 |
#include <type_traits> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
40 |
#include <typeindex> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
41 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
42 |
#include <cereal/macros.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
43 |
#include <cereal/access.hpp> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
44 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
45 |
namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
46 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
47 |
namespace traits |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
48 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
49 |
using yes = std::true_type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
50 |
using no = std::false_type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
51 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
52 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
53 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
54 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
55 |
//! Used to delay a static_assert until template instantiation |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
56 |
template <class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
57 |
struct delay_static_assert : std::false_type {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
58 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
59 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
60 |
// SFINAE Helpers |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
61 |
#ifdef CEREAL_OLDER_GCC // when VS supports better SFINAE, we can use this as the default |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
62 |
template<typename> struct Void { typedef void type; }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
63 |
#endif // CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
64 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
65 |
//! Return type for SFINAE Enablers |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
66 |
enum class sfinae {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
67 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
68 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
69 |
// Helper functionality for boolean integral constants and Enable/DisableIf |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
70 |
template <bool H, bool ... T> struct meta_bool_and : std::integral_constant<bool, H && meta_bool_and<T...>::value> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
71 |
template <bool B> struct meta_bool_and<B> : std::integral_constant<bool, B> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
72 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
73 |
template <bool H, bool ... T> struct meta_bool_or : std::integral_constant<bool, H || meta_bool_or<T...>::value> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
74 |
template <bool B> struct meta_bool_or<B> : std::integral_constant<bool, B> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
75 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
76 |
// workaround needed due to bug in MSVC 2013, see |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
77 |
// http://connect.microsoft.com/VisualStudio/feedback/details/800231/c-11-alias-template-issue |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
78 |
template <bool ... Conditions> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
79 |
struct EnableIfHelper : std::enable_if<meta_bool_and<Conditions...>::value, sfinae> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
80 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
81 |
template <bool ... Conditions> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
82 |
struct DisableIfHelper : std::enable_if<!meta_bool_or<Conditions...>::value, sfinae> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
83 |
} // namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
84 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
85 |
//! Used as the default value for EnableIf and DisableIf template parameters |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
86 |
/*! @relates EnableIf |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
87 |
@relates DisableIf */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
88 |
static const detail::sfinae sfinae = {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
89 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
90 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
91 |
//! Provides a way to enable a function if conditions are met |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
92 |
/*! This is intended to be used in a near identical fashion to std::enable_if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
93 |
while being significantly easier to read at the cost of not allowing for as |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
94 |
complicated of a condition. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
95 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
96 |
This will compile (allow the function) if every condition evaluates to true. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
97 |
at compile time. This should be used with SFINAE to ensure that at least |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
98 |
one other candidate function works when one fails due to an EnableIf. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
99 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
100 |
This should be used as the las template parameter to a function as |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
101 |
an unnamed parameter with a default value of cereal::traits::sfinae: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
102 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
103 |
@code{cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
104 |
// using by making the last template argument variadic |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
105 |
template <class T, EnableIf<std::is_same<T, bool>::value> = sfinae> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
106 |
void func(T t ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
107 |
@endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
108 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
109 |
Note that this performs a logical AND of all conditions, so you will need |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
110 |
to construct more complicated requirements with this fact in mind. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
111 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
112 |
@relates DisableIf |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
113 |
@relates sfinae |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
114 |
@tparam Conditions The conditions which will be logically ANDed to enable the function. */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
115 |
template <bool ... Conditions> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
116 |
using EnableIf = typename detail::EnableIfHelper<Conditions...>::type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
117 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
118 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
119 |
//! Provides a way to disable a function if conditions are met |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
120 |
/*! This is intended to be used in a near identical fashion to std::enable_if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
121 |
while being significantly easier to read at the cost of not allowing for as |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
122 |
complicated of a condition. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
123 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
124 |
This will compile (allow the function) if every condition evaluates to false. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
125 |
This should be used with SFINAE to ensure that at least one other candidate |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
126 |
function works when one fails due to a DisableIf. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
127 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
128 |
This should be used as the las template parameter to a function as |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
129 |
an unnamed parameter with a default value of cereal::traits::sfinae: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
130 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
131 |
@code{cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
132 |
// using by making the last template argument variadic |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
133 |
template <class T, DisableIf<std::is_same<T, bool>::value> = sfinae> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
134 |
void func(T t ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
135 |
@endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
136 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
137 |
This is often used in conjunction with EnableIf to form an enable/disable pair of |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
138 |
overloads. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
139 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
140 |
Note that this performs a logical AND of all conditions, so you will need |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
141 |
to construct more complicated requirements with this fact in mind. If all conditions |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
142 |
hold, the function will be disabled. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
143 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
144 |
@relates EnableIf |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
145 |
@relates sfinae |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
146 |
@tparam Conditions The conditions which will be logically ANDed to disable the function. */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
147 |
template <bool ... Conditions> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
148 |
using DisableIf = typename detail::DisableIfHelper<Conditions...>::type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
149 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
150 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
151 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
152 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
153 |
template <class InputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
154 |
struct get_output_from_input : no |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
155 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
156 |
static_assert( detail::delay_static_assert<InputArchive>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
157 |
"Could not find an associated output archive for input archive." ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
158 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
159 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
160 |
template <class OutputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
161 |
struct get_input_from_output : no |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
162 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
163 |
static_assert( detail::delay_static_assert<OutputArchive>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
164 |
"Could not find an associated input archive for output archive." ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
165 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
166 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
167 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
168 |
//! Sets up traits that relate an input archive to an output archive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
169 |
#define CEREAL_SETUP_ARCHIVE_TRAITS(InputArchive, OutputArchive) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
170 |
namespace cereal { namespace traits { namespace detail { \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
171 |
template <> struct get_output_from_input<InputArchive> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
172 |
{ using type = OutputArchive; }; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
173 |
template <> struct get_input_from_output<OutputArchive> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
174 |
{ using type = InputArchive; }; } } } /* end namespaces */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
175 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
176 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
177 |
//! Used to convert a MAKE_HAS_XXX macro into a versioned variant |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
178 |
#define CEREAL_MAKE_VERSIONED_TEST ,0 |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
179 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
180 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
181 |
//! Creates a test for whether a non const member function exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
182 |
/*! This creates a class derived from std::integral_constant that will be true if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
183 |
the type has the proper member function for the given archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
184 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
185 |
@param name The name of the function to test for (e.g. serialize, load, save) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
186 |
@param test_name The name to give the test for the function being tested for (e.g. serialize, versioned_serialize) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
187 |
@param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
188 |
#ifdef CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
189 |
#define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
190 |
template <class T, class A, class SFINAE = void> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
191 |
struct has_member_##test_name : no {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
192 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
193 |
struct has_member_##test_name<T, A, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
194 |
typename detail::Void< decltype( cereal::access::member_##name( std::declval<A&>(), std::declval<T&>() versioned ) ) >::type> : yes {} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
195 |
#else // NOT CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
196 |
#define CEREAL_MAKE_HAS_MEMBER_TEST(name, test_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
197 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
198 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
199 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
200 |
struct has_member_##name##_##versioned##_impl \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
201 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
202 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
203 |
static auto test(int) -> decltype( cereal::access::member_##name( std::declval<AA&>(), std::declval<TT&>() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
204 |
template <class, class> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
205 |
static no test(...); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
206 |
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
207 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
208 |
} /* end namespace detail */ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
209 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
210 |
struct has_member_##test_name : std::integral_constant<bool, detail::has_member_##name##_##versioned##_impl<T, A>::value> {} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
211 |
#endif // NOT CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
212 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
213 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
214 |
//! Creates a test for whether a non const non-member function exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
215 |
/*! This creates a class derived from std::integral_constant that will be true if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
216 |
the type has the proper non-member function for the given archive. */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
217 |
#define CEREAL_MAKE_HAS_NON_MEMBER_TEST(test_name, func, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
218 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
219 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
220 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
221 |
struct has_non_member_##test_name##_impl \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
222 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
223 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
224 |
static auto test(int) -> decltype( func( std::declval<AA&>(), std::declval<TT&>() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
225 |
template <class, class> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
226 |
static no test( ... ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
227 |
static const bool value = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
228 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
229 |
} /* end namespace detail */ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
230 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
231 |
struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> {} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
232 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
233 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
234 |
// Member Serialize |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
235 |
CEREAL_MAKE_HAS_MEMBER_TEST(serialize, serialize,); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
236 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
237 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
238 |
// Member Serialize (versioned) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
239 |
CEREAL_MAKE_HAS_MEMBER_TEST(serialize, versioned_serialize, CEREAL_MAKE_VERSIONED_TEST); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
240 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
241 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
242 |
// Non Member Serialize |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
243 |
CEREAL_MAKE_HAS_NON_MEMBER_TEST(serialize, CEREAL_SERIALIZE_FUNCTION_NAME,); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
244 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
245 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
246 |
// Non Member Serialize (versioned) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
247 |
CEREAL_MAKE_HAS_NON_MEMBER_TEST(versioned_serialize, CEREAL_SERIALIZE_FUNCTION_NAME, CEREAL_MAKE_VERSIONED_TEST); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
248 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
249 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
250 |
// Member Load |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
251 |
CEREAL_MAKE_HAS_MEMBER_TEST(load, load,); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
252 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
253 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
254 |
// Member Load (versioned) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
255 |
CEREAL_MAKE_HAS_MEMBER_TEST(load, versioned_load, CEREAL_MAKE_VERSIONED_TEST); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
256 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
257 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
258 |
// Non Member Load |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
259 |
CEREAL_MAKE_HAS_NON_MEMBER_TEST(load, CEREAL_LOAD_FUNCTION_NAME,); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
260 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
261 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
262 |
// Non Member Load (versioned) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
263 |
CEREAL_MAKE_HAS_NON_MEMBER_TEST(versioned_load, CEREAL_LOAD_FUNCTION_NAME, CEREAL_MAKE_VERSIONED_TEST); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
264 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
265 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
266 |
#undef CEREAL_MAKE_HAS_NON_MEMBER_TEST |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
267 |
#undef CEREAL_MAKE_HAS_MEMBER_TEST |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
268 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
269 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
270 |
//! Creates a test for whether a member save function exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
271 |
/*! This creates a class derived from std::integral_constant that will be true if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
272 |
the type has the proper member function for the given archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
273 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
274 |
@param test_name The name to give the test (e.g. save or versioned_save) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
275 |
@param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
276 |
#ifdef CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
277 |
#define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
278 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
279 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
280 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
281 |
struct has_member_##test_name##_impl \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
282 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
283 |
template <class TT, class AA, class SFINAE = void> struct test : no {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
284 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
285 |
struct test<TT, AA, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
286 |
typename detail::Void< decltype( cereal::access::member_save( std::declval<AA&>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
287 |
std::declval<TT const &>() versioned ) ) >::type> : yes {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
288 |
static const bool value = test<T, A>(); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
289 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
290 |
template <class TT, class AA, class SFINAE = void> struct test2 : no {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
291 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
292 |
struct test2<TT, AA, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
293 |
typename detail::Void< decltype( cereal::access::member_save_non_const( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
294 |
std::declval<AA&>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
295 |
std::declval<typename std::remove_const<TT>::type&>() versioned ) ) >::type> : yes {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
296 |
static const bool not_const_type = test2<T, A>(); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
297 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
298 |
} /* end namespace detail */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
299 |
#else /* NOT CEREAL_OLDER_GCC =================================== */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
300 |
#define CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(test_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
301 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
302 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
303 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
304 |
struct has_member_##test_name##_impl \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
305 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
306 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
307 |
static auto test(int) -> decltype( cereal::access::member_save( std::declval<AA&>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
308 |
std::declval<TT const &>() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
309 |
template <class, class> static no test(...); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
310 |
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
311 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
312 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
313 |
static auto test2(int) -> decltype( cereal::access::member_save_non_const( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
314 |
std::declval<AA &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
315 |
std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
316 |
template <class, class> static no test2(...); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
317 |
static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
318 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
319 |
} /* end namespace detail */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
320 |
#endif /* NOT CEREAL_OLDER_GCC */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
321 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
322 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
323 |
// Member Save |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
324 |
CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(save, ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
325 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
326 |
template <class T, class A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
327 |
struct has_member_save : std::integral_constant<bool, detail::has_member_save_impl<T, A>::value> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
328 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
329 |
typedef typename detail::has_member_save_impl<T, A> check; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
330 |
static_assert( check::value || !check::not_const_type, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
331 |
"cereal detected a non-const save. \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
332 |
"save member functions must always be const" ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
333 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
334 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
335 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
336 |
// Member Save (versioned) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
337 |
CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL(versioned_save, CEREAL_MAKE_VERSIONED_TEST) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
338 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
339 |
template <class T, class A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
340 |
struct has_member_versioned_save : std::integral_constant<bool, detail::has_member_versioned_save_impl<T, A>::value> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
341 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
342 |
typedef typename detail::has_member_versioned_save_impl<T, A> check; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
343 |
static_assert( check::value || !check::not_const_type, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
344 |
"cereal detected a versioned non-const save. \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
345 |
"save member functions must always be const" ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
346 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
347 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
348 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
349 |
#undef CEREAL_MAKE_HAS_MEMBER_SAVE_IMPL |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
350 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
351 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
352 |
//! Creates a test for whether a non-member save function exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
353 |
/*! This creates a class derived from std::integral_constant that will be true if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
354 |
the type has the proper non-member function for the given archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
355 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
356 |
@param test_name The name to give the test (e.g. save or versioned_save) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
357 |
@param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
358 |
#define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(test_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
359 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
360 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
361 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
362 |
struct has_non_member_##test_name##_impl \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
363 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
364 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
365 |
static auto test(int) -> decltype( CEREAL_SAVE_FUNCTION_NAME( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
366 |
std::declval<AA&>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
367 |
std::declval<TT const &>() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
368 |
template <class, class> static no test(...); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
369 |
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
370 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
371 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
372 |
static auto test2(int) -> decltype( CEREAL_SAVE_FUNCTION_NAME( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
373 |
std::declval<AA &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
374 |
std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
375 |
template <class, class> static no test2(...); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
376 |
static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
377 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
378 |
} /* end namespace detail */ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
379 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
380 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
381 |
struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
382 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
383 |
using check = typename detail::has_non_member_##test_name##_impl<T, A>; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
384 |
static_assert( check::value || !check::not_const_type, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
385 |
"cereal detected a non-const type parameter in non-member " #test_name ". \n " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
386 |
#test_name " non-member functions must always pass their types as const" ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
387 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
388 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
389 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
390 |
// Non Member Save |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
391 |
CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(save, ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
392 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
393 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
394 |
// Non Member Save (versioned) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
395 |
CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST(versioned_save, CEREAL_MAKE_VERSIONED_TEST) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
396 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
397 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
398 |
#undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_TEST |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
399 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
400 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
401 |
// Minimal Utilities |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
402 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
403 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
404 |
// Determines if the provided type is an std::string |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
405 |
template <class> struct is_string : std::false_type {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
406 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
407 |
template <class CharT, class Traits, class Alloc> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
408 |
struct is_string<std::basic_string<CharT, Traits, Alloc>> : std::true_type {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
409 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
410 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
411 |
// Determines if the type is valid for use with a minimal serialize function |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
412 |
template <class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
413 |
struct is_minimal_type : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
414 |
detail::is_string<T>::value || std::is_arithmetic<T>::value> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
415 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
416 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
417 |
//! Creates implementation details for whether a member save_minimal function exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
418 |
/*! This creates a class derived from std::integral_constant that will be true if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
419 |
the type has the proper member function for the given archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
420 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
421 |
@param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
422 |
@param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
423 |
#ifdef CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
424 |
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
425 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
426 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
427 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
428 |
struct has_member_##test_name##_impl \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
429 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
430 |
template <class TT, class AA, class SFINAE = void> struct test : no {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
431 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
432 |
struct test<TT, AA, typename detail::Void< decltype( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
433 |
cereal::access::member_save_minimal( std::declval<AA const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
434 |
std::declval<TT const &>() versioned ) ) >::type> : yes {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
435 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
436 |
static const bool value = test<T, A>(); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
437 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
438 |
template <class TT, class AA, class SFINAE = void> struct test2 : no {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
439 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
440 |
struct test2<TT, AA, typename detail::Void< decltype( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
441 |
cereal::access::member_save_minimal_non_const( std::declval<AA const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
442 |
std::declval<typename std::remove_const<TT>::type&>() versioned ) ) >::type> : yes {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
443 |
static const bool not_const_type = test2<T, A>(); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
444 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
445 |
static const bool valid = value || !not_const_type; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
446 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
447 |
} /* end namespace detail */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
448 |
#else /* NOT CEREAL_OLDER_GCC =================================== */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
449 |
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(test_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
450 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
451 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
452 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
453 |
struct has_member_##test_name##_impl \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
454 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
455 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
456 |
static auto test(int) -> decltype( cereal::access::member_save_minimal( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
457 |
std::declval<AA const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
458 |
std::declval<TT const &>() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
459 |
template <class, class> static no test(...); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
460 |
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
461 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
462 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
463 |
static auto test2(int) -> decltype( cereal::access::member_save_minimal_non_const( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
464 |
std::declval<AA const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
465 |
std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
466 |
template <class, class> static no test2(...); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
467 |
static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
468 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
469 |
static const bool valid = value || !not_const_type; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
470 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
471 |
} /* end namespace detail */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
472 |
#endif // NOT CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
473 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
474 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
475 |
//! Creates helpers for minimal save functions |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
476 |
/*! The get_member_*_type structs allow access to the return type of a save_minimal, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
477 |
assuming that the function actually exists. If the function does not |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
478 |
exist, the type will be void. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
479 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
480 |
@param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
481 |
@param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
482 |
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(test_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
483 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
484 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
485 |
template <class T, class A, bool Valid> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
486 |
struct get_member_##test_name##_type { using type = void; }; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
487 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
488 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
489 |
struct get_member_##test_name##_type<T, A, true> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
490 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
491 |
using type = decltype( cereal::access::member_save_minimal( std::declval<A const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
492 |
std::declval<T const &>() versioned ) ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
493 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
494 |
} /* end namespace detail */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
495 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
496 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
497 |
//! Creates a test for whether a member save_minimal function exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
498 |
/*! This creates a class derived from std::integral_constant that will be true if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
499 |
the type has the proper member function for the given archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
500 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
501 |
@param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal) */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
502 |
#define CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(test_name) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
503 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
504 |
struct has_member_##test_name : std::integral_constant<bool, detail::has_member_##test_name##_impl<T, A>::value> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
505 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
506 |
using check = typename detail::has_member_##test_name##_impl<T, A>; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
507 |
static_assert( check::valid, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
508 |
"cereal detected a non-const member " #test_name ". \n " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
509 |
#test_name " member functions must always be const" ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
510 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
511 |
using type = typename detail::get_member_##test_name##_type<T, A, check::value>::type; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
512 |
static_assert( (check::value && is_minimal_type<type>::value) || !check::value, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
513 |
"cereal detected a member " #test_name " with an invalid return type. \n " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
514 |
"return type must be arithmetic or string" ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
515 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
516 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
517 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
518 |
// Member Save Minimal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
519 |
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(save_minimal, ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
520 |
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(save_minimal, ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
521 |
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(save_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
522 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
523 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
524 |
// Member Save Minimal (versioned) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
525 |
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
526 |
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
527 |
CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST(versioned_save_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
528 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
529 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
530 |
#undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_IMPL |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
531 |
#undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_HELPERS_IMPL |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
532 |
#undef CEREAL_MAKE_HAS_MEMBER_SAVE_MINIMAL_TEST |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
533 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
534 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
535 |
//! Creates a test for whether a non-member save_minimal function exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
536 |
/*! This creates a class derived from std::integral_constant that will be true if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
537 |
the type has the proper member function for the given archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
538 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
539 |
@param test_name The name to give the test (e.g. save_minimal or versioned_save_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
540 |
@param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
541 |
#define CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(test_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
542 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
543 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
544 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
545 |
struct has_non_member_##test_name##_impl \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
546 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
547 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
548 |
static auto test(int) -> decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
549 |
std::declval<AA const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
550 |
std::declval<TT const &>() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
551 |
template <class, class> static no test(...); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
552 |
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
553 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
554 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
555 |
static auto test2(int) -> decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
556 |
std::declval<AA const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
557 |
std::declval<typename std::remove_const<TT>::type&>() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
558 |
template <class, class> static no test2(...); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
559 |
static const bool not_const_type = std::is_same<decltype(test2<T, A>(0)), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
560 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
561 |
static const bool valid = value || !not_const_type; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
562 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
563 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
564 |
template <class T, class A, bool Valid> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
565 |
struct get_non_member_##test_name##_type { using type = void; }; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
566 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
567 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
568 |
struct get_non_member_##test_name##_type <T, A, true> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
569 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
570 |
using type = decltype( CEREAL_SAVE_MINIMAL_FUNCTION_NAME( std::declval<A const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
571 |
std::declval<T const &>() versioned ) ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
572 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
573 |
} /* end namespace detail */ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
574 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
575 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
576 |
struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
577 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
578 |
using check = typename detail::has_non_member_##test_name##_impl<T, A>; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
579 |
static_assert( check::valid, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
580 |
"cereal detected a non-const type parameter in non-member " #test_name ". \n " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
581 |
#test_name " non-member functions must always pass their types as const" ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
582 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
583 |
using type = typename detail::get_non_member_##test_name##_type<T, A, check::value>::type; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
584 |
static_assert( (check::value && is_minimal_type<type>::value) || !check::value, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
585 |
"cereal detected a non-member " #test_name " with an invalid return type. \n " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
586 |
"return type must be arithmetic or string" ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
587 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
588 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
589 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
590 |
// Non-Member Save Minimal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
591 |
CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(save_minimal, ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
592 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
593 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
594 |
// Non-Member Save Minimal (versioned) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
595 |
CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST(versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
596 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
597 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
598 |
#undef CEREAL_MAKE_HAS_NON_MEMBER_SAVE_MINIMAL_TEST |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
599 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
600 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
601 |
// Load Minimal Utilities |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
602 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
603 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
604 |
//! Used to help strip away conversion wrappers |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
605 |
/*! If someone writes a non-member load/save minimal function that accepts its |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
606 |
parameter as some generic template type and needs to perform trait checks |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
607 |
on that type, our NoConvert wrappers will interfere with this. Using |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
608 |
the struct strip_minmal, users can strip away our wrappers to get to |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
609 |
the underlying type, allowing traits to work properly */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
610 |
struct NoConvertBase {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
611 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
612 |
//! A struct that prevents implicit conversion |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
613 |
/*! Any type instantiated with this struct will be unable to implicitly convert |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
614 |
to another type. Is designed to only allow conversion to Source const &. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
615 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
616 |
@tparam Source the type of the original source */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
617 |
template <class Source> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
618 |
struct NoConvertConstRef : NoConvertBase |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
619 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
620 |
using type = Source; //!< Used to get underlying type easily |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
621 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
622 |
template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
623 |
operator Dest () = delete; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
624 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
625 |
//! only allow conversion if the types are the same and we are converting into a const reference |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
626 |
template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
627 |
operator Dest const & (); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
628 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
629 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
630 |
//! A struct that prevents implicit conversion |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
631 |
/*! Any type instantiated with this struct will be unable to implicitly convert |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
632 |
to another type. Is designed to only allow conversion to Source &. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
633 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
634 |
@tparam Source the type of the original source */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
635 |
template <class Source> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
636 |
struct NoConvertRef : NoConvertBase |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
637 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
638 |
using type = Source; //!< Used to get underlying type easily |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
639 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
640 |
template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
641 |
operator Dest () = delete; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
642 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
643 |
#ifdef __clang__ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
644 |
template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
645 |
operator Dest const & () = delete; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
646 |
#endif // __clang__ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
647 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
648 |
//! only allow conversion if the types are the same and we are converting into a const reference |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
649 |
template <class Dest, class = typename std::enable_if<std::is_same<Source, Dest>::value>::type> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
650 |
operator Dest & (); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
651 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
652 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
653 |
//! A type that can implicitly convert to anything else |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
654 |
struct AnyConvert |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
655 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
656 |
template <class Dest> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
657 |
operator Dest & (); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
658 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
659 |
template <class Dest> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
660 |
operator Dest const & () const; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
661 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
662 |
} // namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
663 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
664 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
665 |
//! Creates a test for whether a member load_minimal function exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
666 |
/*! This creates a class derived from std::integral_constant that will be true if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
667 |
the type has the proper member function for the given archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
668 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
669 |
Our strategy here is to first check if a function matching the signature more or less exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
670 |
(allow anything like load_minimal(xxx) using AnyConvert, and then secondly enforce |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
671 |
that it has the correct signature using NoConvertConstRef |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
672 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
673 |
@param test_name The name to give the test (e.g. load_minimal or versioned_load_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
674 |
@param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
675 |
#ifdef CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
676 |
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
677 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
678 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
679 |
template <class T, class A, class SFINAE = void> struct has_member_##test_name##_impl : no {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
680 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
681 |
struct has_member_##test_name##_impl<T, A, typename detail::Void< decltype( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
682 |
cereal::access::member_load_minimal( std::declval<A const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
683 |
std::declval<T &>(), AnyConvert() versioned ) ) >::type> : yes {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
684 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
685 |
template <class T, class A, class U, class SFINAE = void> struct has_member_##test_name##_type_impl : no {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
686 |
template <class T, class A, class U> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
687 |
struct has_member_##test_name##_type_impl<T, A, U, typename detail::Void< decltype( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
688 |
cereal::access::member_load_minimal( std::declval<A const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
689 |
std::declval<T &>(), NoConvertConstRef<U>() versioned ) ) >::type> : yes {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
690 |
} /* end namespace detail */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
691 |
#else /* NOT CEREAL_OLDER_GCC =================================== */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
692 |
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(test_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
693 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
694 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
695 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
696 |
struct has_member_##test_name##_impl \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
697 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
698 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
699 |
static auto test(int) -> decltype( cereal::access::member_load_minimal( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
700 |
std::declval<AA const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
701 |
std::declval<TT &>(), AnyConvert() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
702 |
template <class, class> static no test(...); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
703 |
static const bool value = std::is_same<decltype(test<T, A>(0)), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
704 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
705 |
template <class T, class A, class U> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
706 |
struct has_member_##test_name##_type_impl \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
707 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
708 |
template <class TT, class AA, class UU> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
709 |
static auto test(int) -> decltype( cereal::access::member_load_minimal( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
710 |
std::declval<AA const &>(), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
711 |
std::declval<TT &>(), NoConvertConstRef<UU>() versioned ), yes()); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
712 |
template <class, class, class> static no test(...); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
713 |
static const bool value = std::is_same<decltype(test<T, A, U>(0)), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
714 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
715 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
716 |
} /* end namespace detail */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
717 |
#endif // NOT CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
718 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
719 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
720 |
//! Creates helpers for minimal load functions |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
721 |
/*! The has_member_*_wrapper structs ensure that the load and save types for the |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
722 |
requested function type match appropriately. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
723 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
724 |
@param load_test_name The name to give the test (e.g. load_minimal or versioned_load_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
725 |
@param save_test_name The name to give the test (e.g. save_minimal or versioned_save_minimal, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
726 |
should match the load name. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
727 |
@param save_test_prefix The name to give the test (e.g. save_minimal or versioned_save_minimal, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
728 |
should match the load name, without the trailing "_minimal" (e.g. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
729 |
save or versioned_save). Needed because the preprocessor is an abomination. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
730 |
@param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
731 |
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_test_name, save_test_name, save_test_prefix, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
732 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
733 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
734 |
template <class T, class A, bool Valid> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
735 |
struct has_member_##load_test_name##_wrapper : std::false_type {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
736 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
737 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
738 |
struct has_member_##load_test_name##_wrapper<T, A, true> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
739 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
740 |
using AOut = typename detail::get_output_from_input<A>::type; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
741 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
742 |
static_assert( has_member_##save_test_prefix##_minimal<T, AOut>::value, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
743 |
"cereal detected member " #load_test_name " but no valid member " #save_test_name ". \n " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
744 |
"cannot evaluate correctness of " #load_test_name " without valid " #save_test_name "." ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
745 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
746 |
using SaveType = typename detail::get_member_##save_test_prefix##_minimal_type<T, AOut, true>::type; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
747 |
const static bool value = has_member_##load_test_name##_impl<T, A>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
748 |
const static bool valid = has_member_##load_test_name##_type_impl<T, A, SaveType>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
749 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
750 |
static_assert( valid || !value, "cereal detected different or invalid types in corresponding member " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
751 |
#load_test_name " and " #save_test_name " functions. \n " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
752 |
"the paramater to " #load_test_name " must be a constant reference to the type that " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
753 |
#save_test_name " returns." ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
754 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
755 |
} /* end namespace detail */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
756 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
757 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
758 |
//! Creates a test for whether a member load_minimal function exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
759 |
/*! This creates a class derived from std::integral_constant that will be true if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
760 |
the type has the proper member function for the given archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
761 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
762 |
@param load_test_name The name to give the test (e.g. load_minimal or versioned_load_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
763 |
@param load_test_prefix The above parameter minus the trailing "_minimal" */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
764 |
#define CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_test_name, load_test_prefix) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
765 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
766 |
struct has_member_##load_test_prefix##_minimal : std::integral_constant<bool, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
767 |
detail::has_member_##load_test_name##_wrapper<T, A, detail::has_member_##load_test_name##_impl<T, A>::value>::value> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
768 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
769 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
770 |
// Member Load Minimal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
771 |
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(load_minimal, ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
772 |
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(load_minimal, save_minimal, save, ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
773 |
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(load_minimal, load) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
774 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
775 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
776 |
// Member Load Minimal (versioned) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
777 |
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL(versioned_load_minimal, CEREAL_MAKE_VERSIONED_TEST) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
778 |
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL(versioned_load_minimal, versioned_save_minimal, versioned_save, CEREAL_MAKE_VERSIONED_TEST) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
779 |
CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_load) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
780 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
781 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
782 |
#undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_IMPL |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
783 |
#undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_HELPERS_IMPL |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
784 |
#undef CEREAL_MAKE_HAS_MEMBER_LOAD_MINIMAL_TEST |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
785 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
786 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
787 |
// Non-Member Load Minimal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
788 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
789 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
790 |
#ifdef CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
791 |
void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(); // prevents nonsense complaining about not finding this |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
792 |
void CEREAL_SAVE_MINIMAL_FUNCTION_NAME(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
793 |
#endif // CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
794 |
} // namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
795 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
796 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
797 |
//! Creates a test for whether a non-member load_minimal function exists |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
798 |
/*! This creates a class derived from std::integral_constant that will be true if |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
799 |
the type has the proper member function for the given archive. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
800 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
801 |
See notes from member load_minimal implementation. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
802 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
803 |
@param test_name The name to give the test (e.g. load_minimal or versioned_load_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
804 |
@param save_name The corresponding name the save test would have (e.g. save_minimal or versioned_save_minimal) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
805 |
@param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
806 |
#define CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(test_name, save_name, versioned) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
807 |
namespace detail \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
808 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
809 |
template <class T, class A, class U = void> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
810 |
struct has_non_member_##test_name##_impl \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
811 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
812 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
813 |
static auto test(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
814 |
std::declval<AA const &>(), std::declval<TT&>(), AnyConvert() versioned ), yes() ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
815 |
template <class, class> static no test( ... ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
816 |
static const bool exists = std::is_same<decltype( test<T, A>( 0 ) ), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
817 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
818 |
template <class TT, class AA, class UU> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
819 |
static auto test2(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
820 |
std::declval<AA const &>(), std::declval<TT&>(), NoConvertConstRef<UU>() versioned ), yes() ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
821 |
template <class, class, class> static no test2( ... ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
822 |
static const bool valid = std::is_same<decltype( test2<T, A, U>( 0 ) ), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
823 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
824 |
template <class TT, class AA> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
825 |
static auto test3(int) -> decltype( CEREAL_LOAD_MINIMAL_FUNCTION_NAME( \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
826 |
std::declval<AA const &>(), NoConvertRef<TT>(), AnyConvert() versioned ), yes() ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
827 |
template <class, class> static no test3( ... ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
828 |
static const bool const_valid = std::is_same<decltype( test3<T, A>( 0 ) ), yes>::value; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
829 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
830 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
831 |
template <class T, class A, bool Valid> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
832 |
struct has_non_member_##test_name##_wrapper : std::false_type {}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
833 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
834 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
835 |
struct has_non_member_##test_name##_wrapper<T, A, true> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
836 |
{ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
837 |
using AOut = typename detail::get_output_from_input<A>::type; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
838 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
839 |
static_assert( detail::has_non_member_##save_name##_impl<T, AOut>::valid, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
840 |
"cereal detected non-member " #test_name " but no valid non-member " #save_name ". \n " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
841 |
"cannot evaluate correctness of " #test_name " without valid " #save_name "." ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
842 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
843 |
using SaveType = typename detail::get_non_member_##save_name##_type<T, AOut, true>::type; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
844 |
using check = has_non_member_##test_name##_impl<T, A, SaveType>; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
845 |
static const bool value = check::exists; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
846 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
847 |
static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
848 |
#test_name " and " #save_name " functions. \n " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
849 |
"the paramater to " #test_name " must be a constant reference to the type that " #save_name " returns." ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
850 |
static_assert( check::const_valid || !check::exists, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
851 |
"cereal detected an invalid serialization type parameter in non-member " #test_name ". " \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
852 |
#test_name " non-member functions must accept their serialization type by non-const reference" ); \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
853 |
}; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
854 |
} /* namespace detail */ \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
855 |
\ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
856 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
857 |
struct has_non_member_##test_name : std::integral_constant<bool, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
858 |
detail::has_non_member_##test_name##_wrapper<T, A, detail::has_non_member_##test_name##_impl<T, A>::exists>::value> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
859 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
860 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
861 |
// Non-Member Load Minimal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
862 |
CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(load_minimal, save_minimal, ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
863 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
864 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
865 |
// Non-Member Load Minimal (versioned) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
866 |
CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST(versioned_load_minimal, versioned_save_minimal, CEREAL_MAKE_VERSIONED_TEST) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
867 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
868 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
869 |
#undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
870 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
871 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
872 |
// End of serialization existence tests |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
873 |
#undef CEREAL_MAKE_VERSIONED_TEST |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
874 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
875 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
876 |
template <class T, class InputArchive, class OutputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
877 |
struct has_member_split : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
878 |
(has_member_load<T, InputArchive>::value && has_member_save<T, OutputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
879 |
(has_member_versioned_load<T, InputArchive>::value && has_member_versioned_save<T, OutputArchive>::value)> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
880 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
881 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
882 |
template <class T, class InputArchive, class OutputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
883 |
struct has_non_member_split : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
884 |
(has_non_member_load<T, InputArchive>::value && has_non_member_save<T, OutputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
885 |
(has_non_member_versioned_load<T, InputArchive>::value && has_non_member_versioned_save<T, OutputArchive>::value)> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
886 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
887 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
888 |
template <class T, class OutputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
889 |
struct has_invalid_output_versioning : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
890 |
(has_member_versioned_save<T, OutputArchive>::value && has_member_save<T, OutputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
891 |
(has_non_member_versioned_save<T, OutputArchive>::value && has_non_member_save<T, OutputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
892 |
(has_member_versioned_serialize<T, OutputArchive>::value && has_member_serialize<T, OutputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
893 |
(has_non_member_versioned_serialize<T, OutputArchive>::value && has_non_member_serialize<T, OutputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
894 |
(has_member_versioned_save_minimal<T, OutputArchive>::value && has_member_save_minimal<T, OutputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
895 |
(has_non_member_versioned_save_minimal<T, OutputArchive>::value && has_non_member_save_minimal<T, OutputArchive>::value)> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
896 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
897 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
898 |
template <class T, class InputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
899 |
struct has_invalid_input_versioning : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
900 |
(has_member_versioned_load<T, InputArchive>::value && has_member_load<T, InputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
901 |
(has_non_member_versioned_load<T, InputArchive>::value && has_non_member_load<T, InputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
902 |
(has_member_versioned_serialize<T, InputArchive>::value && has_member_serialize<T, InputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
903 |
(has_non_member_versioned_serialize<T, InputArchive>::value && has_non_member_serialize<T, InputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
904 |
(has_member_versioned_load_minimal<T, InputArchive>::value && has_member_load_minimal<T, InputArchive>::value) || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
905 |
(has_non_member_versioned_load_minimal<T, InputArchive>::value && has_non_member_load_minimal<T, InputArchive>::value)> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
906 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
907 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
908 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
909 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
910 |
//! Create a test for a cereal::specialization entry |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
911 |
#define CEREAL_MAKE_IS_SPECIALIZED_IMPL(name) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
912 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
913 |
struct is_specialized_##name : std::integral_constant<bool, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
914 |
!std::is_base_of<std::false_type, specialize<A, T, specialization::name>>::value> {} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
915 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
916 |
CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_serialize); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
917 |
CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
918 |
CEREAL_MAKE_IS_SPECIALIZED_IMPL(member_load_save_minimal); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
919 |
CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_serialize); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
920 |
CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
921 |
CEREAL_MAKE_IS_SPECIALIZED_IMPL(non_member_load_save_minimal); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
922 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
923 |
#undef CEREAL_MAKE_IS_SPECIALIZED_IMPL |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
924 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
925 |
//! Number of specializations detected |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
926 |
template <class T, class A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
927 |
struct count_specializations : std::integral_constant<int, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
928 |
is_specialized_member_serialize<T, A>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
929 |
is_specialized_member_load_save<T, A>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
930 |
is_specialized_member_load_save_minimal<T, A>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
931 |
is_specialized_non_member_serialize<T, A>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
932 |
is_specialized_non_member_load_save<T, A>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
933 |
is_specialized_non_member_load_save_minimal<T, A>::value> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
934 |
} // namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
935 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
936 |
//! Check if any specialization exists for a type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
937 |
template <class T, class A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
938 |
struct is_specialized : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
939 |
detail::is_specialized_member_serialize<T, A>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
940 |
detail::is_specialized_member_load_save<T, A>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
941 |
detail::is_specialized_member_load_save_minimal<T, A>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
942 |
detail::is_specialized_non_member_serialize<T, A>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
943 |
detail::is_specialized_non_member_load_save<T, A>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
944 |
detail::is_specialized_non_member_load_save_minimal<T, A>::value> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
945 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
946 |
static_assert(detail::count_specializations<T, A>::value <= 1, "More than one explicit specialization detected for type."); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
947 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
948 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
949 |
//! Create the static assertion for some specialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
950 |
/*! This assertion will fail if the type is indeed specialized and does not have the appropriate |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
951 |
type of serialization functions */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
952 |
#define CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, print_name, spec_name) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
953 |
static_assert( (is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value && \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
954 |
(has_##name<T, A>::value || has_##versioned_name<T, A>::value)) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
955 |
|| !(is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value), \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
956 |
"cereal detected " #print_name " specialization but no " #print_name " serialize function" ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
957 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
958 |
//! Generates a test for specialization for versioned and unversioned functions |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
959 |
/*! This creates checks that can be queried to see if a given type of serialization function |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
960 |
has been specialized for this type */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
961 |
#define CEREAL_MAKE_IS_SPECIALIZED(name, versioned_name, spec_name) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
962 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
963 |
struct is_specialized_##name : std::integral_constant<bool, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
964 |
is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
965 |
{ CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, name, spec_name); }; \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
966 |
template <class T, class A> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
967 |
struct is_specialized_##versioned_name : std::integral_constant<bool, \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
968 |
is_specialized<T, A>::value && detail::is_specialized_##spec_name<T, A>::value> \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
969 |
{ CEREAL_MAKE_IS_SPECIALIZED_ASSERT(name, versioned_name, versioned_name, spec_name); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
970 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
971 |
CEREAL_MAKE_IS_SPECIALIZED(member_serialize, member_versioned_serialize, member_serialize); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
972 |
CEREAL_MAKE_IS_SPECIALIZED(non_member_serialize, non_member_versioned_serialize, non_member_serialize); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
973 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
974 |
CEREAL_MAKE_IS_SPECIALIZED(member_save, member_versioned_save, member_load_save); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
975 |
CEREAL_MAKE_IS_SPECIALIZED(non_member_save, non_member_versioned_save, non_member_load_save); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
976 |
CEREAL_MAKE_IS_SPECIALIZED(member_load, member_versioned_load, member_load_save); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
977 |
CEREAL_MAKE_IS_SPECIALIZED(non_member_load, non_member_versioned_load, non_member_load_save); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
978 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
979 |
CEREAL_MAKE_IS_SPECIALIZED(member_save_minimal, member_versioned_save_minimal, member_load_save_minimal); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
980 |
CEREAL_MAKE_IS_SPECIALIZED(non_member_save_minimal, non_member_versioned_save_minimal, non_member_load_save_minimal); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
981 |
CEREAL_MAKE_IS_SPECIALIZED(member_load_minimal, member_versioned_load_minimal, member_load_save_minimal); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
982 |
CEREAL_MAKE_IS_SPECIALIZED(non_member_load_minimal, non_member_versioned_load_minimal, non_member_load_save_minimal); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
983 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
984 |
#undef CEREAL_MAKE_IS_SPECIALIZED_ASSERT |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
985 |
#undef CEREAL_MAKE_IS_SPECIALIZED |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
986 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
987 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
988 |
// detects if a type has any active minimal output serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
989 |
template <class T, class OutputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
990 |
struct has_minimal_output_serialization : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
991 |
is_specialized_member_save_minimal<T, OutputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
992 |
((has_member_save_minimal<T, OutputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
993 |
has_non_member_save_minimal<T, OutputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
994 |
has_member_versioned_save_minimal<T, OutputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
995 |
has_non_member_versioned_save_minimal<T, OutputArchive>::value) && |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
996 |
!(is_specialized_member_serialize<T, OutputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
997 |
is_specialized_member_save<T, OutputArchive>::value))> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
998 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
999 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1000 |
// detects if a type has any active minimal input serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1001 |
template <class T, class InputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1002 |
struct has_minimal_input_serialization : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1003 |
is_specialized_member_load_minimal<T, InputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1004 |
((has_member_load_minimal<T, InputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1005 |
has_non_member_load_minimal<T, InputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1006 |
has_member_versioned_load_minimal<T, InputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1007 |
has_non_member_versioned_load_minimal<T, InputArchive>::value) && |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1008 |
!(is_specialized_member_serialize<T, InputArchive>::value || |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1009 |
is_specialized_member_load<T, InputArchive>::value))> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1010 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1011 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1012 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1013 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1014 |
//! The number of output serialization functions available |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1015 |
/*! If specialization is being used, we'll count only those; otherwise we'll count everything */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1016 |
template <class T, class OutputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1017 |
struct count_output_serializers : std::integral_constant<int, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1018 |
count_specializations<T, OutputArchive>::value ? count_specializations<T, OutputArchive>::value : |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1019 |
has_member_save<T, OutputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1020 |
has_non_member_save<T, OutputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1021 |
has_member_serialize<T, OutputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1022 |
has_non_member_serialize<T, OutputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1023 |
has_member_save_minimal<T, OutputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1024 |
has_non_member_save_minimal<T, OutputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1025 |
/*-versioned---------------------------------------------------------*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1026 |
has_member_versioned_save<T, OutputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1027 |
has_non_member_versioned_save<T, OutputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1028 |
has_member_versioned_serialize<T, OutputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1029 |
has_non_member_versioned_serialize<T, OutputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1030 |
has_member_versioned_save_minimal<T, OutputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1031 |
has_non_member_versioned_save_minimal<T, OutputArchive>::value> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1032 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1033 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1034 |
template <class T, class OutputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1035 |
struct is_output_serializable : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1036 |
detail::count_output_serializers<T, OutputArchive>::value == 1> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1037 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1038 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1039 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1040 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1041 |
//! The number of input serialization functions available |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1042 |
/*! If specialization is being used, we'll count only those; otherwise we'll count everything */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1043 |
template <class T, class InputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1044 |
struct count_input_serializers : std::integral_constant<int, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1045 |
count_specializations<T, InputArchive>::value ? count_specializations<T, InputArchive>::value : |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1046 |
has_member_load<T, InputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1047 |
has_non_member_load<T, InputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1048 |
has_member_serialize<T, InputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1049 |
has_non_member_serialize<T, InputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1050 |
has_member_load_minimal<T, InputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1051 |
has_non_member_load_minimal<T, InputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1052 |
/*-versioned---------------------------------------------------------*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1053 |
has_member_versioned_load<T, InputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1054 |
has_non_member_versioned_load<T, InputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1055 |
has_member_versioned_serialize<T, InputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1056 |
has_non_member_versioned_serialize<T, InputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1057 |
has_member_versioned_load_minimal<T, InputArchive>::value + |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1058 |
has_non_member_versioned_load_minimal<T, InputArchive>::value> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1059 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1060 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1061 |
template <class T, class InputArchive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1062 |
struct is_input_serializable : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1063 |
detail::count_input_serializers<T, InputArchive>::value == 1> {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1064 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1065 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1066 |
// Base Class Support |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1067 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1068 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1069 |
struct base_class_id |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1070 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1071 |
template<class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1072 |
base_class_id(T const * const t) : |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1073 |
type(typeid(T)), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1074 |
ptr(t), |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1075 |
hash(std::hash<std::type_index>()(typeid(T)) ^ (std::hash<void const *>()(t) << 1)) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1076 |
{ } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1077 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1078 |
bool operator==(base_class_id const & other) const |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1079 |
{ return (type == other.type) && (ptr == other.ptr); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1080 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1081 |
std::type_index type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1082 |
void const * ptr; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1083 |
size_t hash; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1084 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1085 |
struct base_class_id_hash { size_t operator()(base_class_id const & id) const { return id.hash; } }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1086 |
} // namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1087 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1088 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1089 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1090 |
//! Common base type for base class casting |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1091 |
struct BaseCastBase {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1092 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1093 |
template <class> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1094 |
struct get_base_class; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1095 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1096 |
template <template<typename> class Cast, class Base> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1097 |
struct get_base_class<Cast<Base>> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1098 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1099 |
using type = Base; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1100 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1101 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1102 |
//! Base class cast, behave as the test |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1103 |
template <class Cast, template<class, class> class Test, class Archive, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1104 |
bool IsBaseCast = std::is_base_of<BaseCastBase, Cast>::value> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1105 |
struct has_minimal_base_class_serialization_impl : Test<typename get_base_class<Cast>::type, Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1106 |
{ }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1107 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1108 |
//! Not a base class cast |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1109 |
template <class Cast, template<class, class> class Test, class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1110 |
struct has_minimal_base_class_serialization_impl<Cast,Test, Archive, false> : std::false_type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1111 |
{ }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1112 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1113 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1114 |
//! Checks to see if the base class used in a cast has a minimal serialization |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1115 |
/*! @tparam Cast Either base_class or virtual_base_class wrapped type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1116 |
@tparam Test A has_minimal test (for either input or output) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1117 |
@tparam Archive The archive to use with the test */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1118 |
template <class Cast, template<class, class> class Test, class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1119 |
struct has_minimal_base_class_serialization : detail::has_minimal_base_class_serialization_impl<Cast, Test, Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1120 |
{ }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1121 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1122 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1123 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1124 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1125 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1126 |
struct shared_from_this_wrapper |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1127 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1128 |
template <class U> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1129 |
static auto check( U const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1130 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1131 |
static auto check( ... ) -> decltype( std::false_type() ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1132 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1133 |
template <class U> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1134 |
static auto get( U const & t ) -> decltype( t.shared_from_this() ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1135 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1136 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1137 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1138 |
//! Determine if T or any base class of T has inherited from std::enable_shared_from_this |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1139 |
template<class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1140 |
struct has_shared_from_this : decltype(detail::shared_from_this_wrapper::check(std::declval<T>())) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1141 |
{ }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1142 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1143 |
//! Get the type of the base class of T which inherited from std::enable_shared_from_this |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1144 |
template <class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1145 |
struct get_shared_from_this_base |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1146 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1147 |
private: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1148 |
using PtrType = decltype(detail::shared_from_this_wrapper::get(std::declval<T>())); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1149 |
public: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1150 |
//! The type of the base of T that inherited from std::enable_shared_from_this |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1151 |
using type = typename std::decay<typename PtrType::element_type>::type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1152 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1153 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1154 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1155 |
//! Extracts the true type from something possibly wrapped in a cereal NoConvert |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1156 |
/*! Internally cereal uses some wrapper classes to test the validity of non-member |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1157 |
minimal load and save functions. This can interfere with user type traits on |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1158 |
templated load and save minimal functions. To get to the correct underlying type, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1159 |
users should use strip_minimal when performing any enable_if type type trait checks. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1160 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1161 |
See the enum serialization in types/common.hpp for an example of using this */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1162 |
template <class T, bool IsCerealMinimalTrait = std::is_base_of<detail::NoConvertBase, T>::value> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1163 |
struct strip_minimal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1164 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1165 |
using type = T; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1166 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1167 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1168 |
//! Specialization for types wrapped in a NoConvert |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1169 |
template <class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1170 |
struct strip_minimal<T, true> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1171 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1172 |
using type = typename T::type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1173 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1174 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1175 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1176 |
//! Member load and construct check |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1177 |
template<typename T, typename A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1178 |
struct has_member_load_and_construct : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1179 |
std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1180 |
{ }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1181 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1182 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1183 |
//! Non member load and construct check |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1184 |
template<typename T, typename A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1185 |
struct has_non_member_load_and_construct : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1186 |
std::is_same<decltype( LoadAndConstruct<T>::load_and_construct( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1187 |
{ }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1188 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1189 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1190 |
//! Has either a member or non member allocate |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1191 |
template<typename T, typename A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1192 |
struct has_load_and_construct : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1193 |
has_member_load_and_construct<T, A>::value || has_non_member_load_and_construct<T, A>::value> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1194 |
{ }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1195 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1196 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1197 |
//! Determines whether the class T can be default constructed by cereal::access |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1198 |
template <class T> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1199 |
struct is_default_constructible |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1200 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1201 |
#ifdef CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1202 |
template <class TT, class SFINAE = void> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1203 |
struct test : no {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1204 |
template <class TT> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1205 |
struct test<TT, typename detail::Void< decltype( cereal::access::construct<TT>() ) >::type> : yes {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1206 |
static const bool value = test<T>(); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1207 |
#else // NOT CEREAL_OLDER_GCC ========================================= |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1208 |
template <class TT> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1209 |
static auto test(int) -> decltype( cereal::access::construct<TT>(), yes()); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1210 |
template <class> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1211 |
static no test(...); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1212 |
static const bool value = std::is_same<decltype(test<T>(0)), yes>::value; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1213 |
#endif // NOT CEREAL_OLDER_GCC |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1214 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1215 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1216 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1217 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1218 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1219 |
//! Removes all qualifiers and minimal wrappers from an archive |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1220 |
template <class A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1221 |
using decay_archive = typename std::decay<typename strip_minimal<A>::type>::type; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1222 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1223 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1224 |
//! Checks if the provided archive type is equal to some cereal archive type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1225 |
/*! This automatically does things such as std::decay and removing any other wrappers that may be |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1226 |
on the Archive template parameter. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1227 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1228 |
Example use: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1229 |
@code{cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1230 |
// example use to disable a serialization function |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1231 |
template <class Archive, EnableIf<cereal::traits::is_same_archive<Archive, cereal::BinaryOutputArchive>::value> = sfinae> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1232 |
void save( Archive & ar, MyType const & mt ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1233 |
@endcode */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1234 |
template <class ArchiveT, class CerealArchiveT> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1235 |
struct is_same_archive : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1236 |
std::is_same<detail::decay_archive<ArchiveT>, CerealArchiveT>::value> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1237 |
{ }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1238 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1239 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1240 |
//! A macro to use to restrict which types of archives your function will work for. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1241 |
/*! This requires you to have a template class parameter named Archive and replaces the void return |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1242 |
type for your function. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1243 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1244 |
INTYPE refers to the input archive type you wish to restrict on. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1245 |
OUTTYPE refers to the output archive type you wish to restrict on. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1246 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1247 |
For example, if we want to limit a serialize to only work with binary serialization: |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1248 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1249 |
@code{.cpp} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1250 |
template <class Archive> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1251 |
CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1252 |
serialize( Archive & ar, MyCoolType & m ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1253 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1254 |
ar & m; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1255 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1256 |
@endcode |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1257 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1258 |
If you need to do more restrictions in your enable_if, you will need to do this by hand. |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1259 |
*/ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1260 |
#define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1261 |
typename std::enable_if<cereal::traits::is_same_archive<Archive, INTYPE>::value || cereal::traits::is_same_archive<Archive, OUTTYPE>::value, void>::type |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1262 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1263 |
//! Type traits only struct used to mark an archive as human readable (text based) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1264 |
/*! Archives that wish to identify as text based/human readable should inherit from |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1265 |
this struct */ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1266 |
struct TextArchive {}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1267 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1268 |
//! Checks if an archive is a text archive (human readable) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1269 |
template <class A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1270 |
struct is_text_archive : std::integral_constant<bool, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1271 |
std::is_base_of<TextArchive, detail::decay_archive<A>>::value> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1272 |
{ }; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1273 |
} // namespace traits |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1274 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1275 |
// ###################################################################### |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1276 |
namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1277 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
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> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1279 |
struct Construct |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1280 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1281 |
static_assert( cereal::traits::detail::delay_static_assert<T>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1282 |
"Cereal detected both member and non member load_and_construct functions!" ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1283 |
static T * load_andor_construct( A & /*ar*/, construct<T> & /*construct*/ ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1284 |
{ return nullptr; } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1285 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1286 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1287 |
template <class T, class A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1288 |
struct Construct<T, A, false, false> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1289 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1290 |
static_assert( ::cereal::traits::is_default_constructible<T>::value, |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1291 |
"Trying to serialize a an object with no default constructor. \n\n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1292 |
"Types must either be default constructible or define either a member or non member Construct function. \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1293 |
"Construct functions generally have the signature: \n\n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1294 |
"template <class Archive> \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1295 |
"static void load_and_construct(Archive & ar, cereal::construct<T> & construct) \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1296 |
"{ \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1297 |
" var a; \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1298 |
" ar( a ) \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1299 |
" construct( a ); \n " |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1300 |
"} \n\n" ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1301 |
static T * load_andor_construct() |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1302 |
{ return ::cereal::access::construct<T>(); } |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1303 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1304 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1305 |
template <class T, class A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1306 |
struct Construct<T, A, true, false> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1307 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1308 |
static void load_andor_construct( A & ar, construct<T> & construct ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1309 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1310 |
access::load_and_construct<T>( ar, construct ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1311 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1312 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1313 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1314 |
template <class T, class A> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1315 |
struct Construct<T, A, false, true> |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1316 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1317 |
static void load_andor_construct( A & ar, construct<T> & construct ) |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1318 |
{ |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1319 |
LoadAndConstruct<T>::load_and_construct( ar, construct ); |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1320 |
} |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1321 |
}; |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1322 |
} // namespace detail |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1323 |
} // namespace cereal |
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1324 |
|
| 7a956470 |
sago007 |
2016-02-14 17:09 |
1325 |
#endif // CEREAL_DETAILS_TRAITS_HPP_ |
|
|
1970-01-01 00:00 |
1326 |
|