27 #ifndef CEREAL_DETAILS_TRAITS_HPP_
28 #define CEREAL_DETAILS_TRAITS_HPP_
30 #include <type_traits>
34 #include <cereal/access.hpp>
40 template<
typename>
struct Void {
typedef void type; };
44 template<
typename T,
typename A>
45 bool constexpr has_member_load_and_allocate()
46 {
return std::is_same<decltype( access::load_and_allocate<T>( std::declval<A&>() ) ), T*>::value; }
50 template<
typename T,
typename A>
51 bool constexpr has_non_member_load_and_allocate()
52 {
return std::is_same<decltype( LoadAndAllocate<T>::load_and_allocate( std::declval<A&>() ) ), T*>::value; }
56 template<
typename T,
typename A>
57 bool constexpr has_load_and_allocate()
58 {
return has_member_load_and_allocate<T, A>() || has_non_member_load_and_allocate<T, A>(); }
62 template<
typename T,
class A,
typename Sfinae =
void>
65 template<
typename T,
class A>
68 decltype(
access::member_serialize(std::declval<A&>(), std::declval<T&>() ) )
74 char & serialize(...);
75 template<
typename T,
typename A>
76 bool constexpr has_non_member_serialize()
77 {
return std::is_void<decltype(serialize(std::declval<A&>(), std::declval<T&>()))>::value; };
81 template<
typename T,
class A,
typename Sfinae =
void>
84 template<
typename T,
class A>
87 decltype(
access::member_load(std::declval<A&>(), std::declval<T&>() ) )
94 template<
typename T,
typename A>
95 bool constexpr has_non_member_load()
96 {
return std::is_void<decltype(load(std::declval<A&>(), std::declval<T&>()))>::value; };
100 template<
typename T,
class A,
typename Sfinae =
void>
103 template<
typename T,
class A>
106 decltype(
access::member_save(std::declval<A&>(), std::declval<T const &>() ) )
108 >: std::true_type {};
115 template<
typename T,
class A,
typename Sfinae =
void>
118 template<
typename T,
class A>
121 decltype(
access::non_const_member_save(std::declval<A&>(), std::declval<typename std::remove_const<T>::type &>() ) )
123 >: std::true_type {};
127 template <
class T,
class A>
128 constexpr
bool is_non_const_member_save()
136 template<
typename T,
typename A>
137 bool constexpr has_non_member_save()
138 {
return std::is_void<decltype(save(std::declval<A&>(), std::declval<T const &>()))>::value; }
144 template<
typename T,
typename A>
145 bool constexpr has_non_member_save_any()
146 {
return std::is_void<decltype(save(std::declval<A&>(), std::declval<
typename std::remove_const<T>::type &>()))>::value; }
150 template<
typename T,
typename A>
151 bool constexpr is_non_const_non_member_save()
152 {
return !has_non_member_save<T, A>() && detail::has_non_member_save_any<T, A>(); }
156 template <
class T,
class A>
157 bool constexpr has_non_const_save()
158 {
return is_non_const_member_save<T, A>() || is_non_const_non_member_save<T, A>(); }
161 template <
class T,
class InputArchive,
class OutputArchive>
162 constexpr
bool has_member_split()
163 {
return has_member_load<T, InputArchive>() && has_member_save<T, OutputArchive>(); }
166 template <
class T,
class InputArchive,
class OutputArchive>
167 constexpr
bool has_non_member_split()
168 {
return has_non_member_load<T, InputArchive>() && has_non_member_save<T, OutputArchive>(); }
171 template <
class T,
class OutputArchive>
172 constexpr
bool is_output_serializable()
174 static_assert( !has_non_const_save<T, OutputArchive>(),
175 "cereal detected a non const save. \n "
176 "save functions must either be const member functions or accept const type aguments if non-member" );
179 has_member_save<T, OutputArchive>() ^
180 has_non_member_save<T, OutputArchive>() ^
181 has_member_serialize<T, OutputArchive>() ^
182 has_non_member_serialize<T, OutputArchive>();
186 template <
class T,
class InputArchive>
187 constexpr
bool is_input_serializable()
190 has_member_load<T, InputArchive>() ^
191 has_non_member_load<T, InputArchive>() ^
192 has_member_serialize<T, InputArchive>() ^
193 has_non_member_serialize<T, InputArchive>();
200 template <
class T,
class A>
201 constexpr
auto is_specialized_member_serialize() ->
bool
202 {
return !std::is_base_of<std::false_type, specialize<A, T, specialization::member_serialize>>(); }
204 template <
class T,
class A>
205 constexpr
auto is_specialized_member_load_save() ->
bool
206 {
return !std::is_base_of<std::false_type, specialize<A, T, specialization::member_load_save>>(); }
208 template <
class T,
class A>
209 constexpr
auto is_specialized_non_member_serialize() ->
bool
210 {
return !std::is_base_of<std::false_type, specialize<A, T, specialization::non_member_serialize>>(); }
212 template <
class T,
class A>
213 constexpr
auto is_specialized_non_member_load_save() ->
bool
214 {
return !std::is_base_of<std::false_type, specialize<A, T, specialization::non_member_load_save>>(); }
217 template <
class T,
class A>
218 constexpr
auto is_specialized_error() ->
bool
220 return (is_specialized_member_serialize<T, A>() +
221 is_specialized_member_load_save<T, A>() +
222 is_specialized_non_member_serialize<T, A>() +
223 is_specialized_non_member_load_save<T, A>()) <= 1;
227 template <
class T,
class A>
228 constexpr
auto is_specialized() ->
bool
230 static_assert(detail::is_specialized_error<T, A>(),
"More than one explicit specialization detected for type.");
231 return detail::is_specialized_member_serialize<T, A>() ||
232 detail::is_specialized_member_load_save<T, A>() ||
233 detail::is_specialized_non_member_serialize<T, A>() ||
234 detail::is_specialized_non_member_load_save<T, A>();
237 template <
class T,
class A>
238 constexpr
auto is_specialized_member_serialize() ->
bool
240 static_assert( (is_specialized<T, A>() && detail::is_specialized_member_serialize<T, A>() && has_member_serialize<T, A>())
241 || !(is_specialized<T, A>() && detail::is_specialized_member_serialize<T, A>()),
242 "cereal detected member serialization specialization but no member serialize function" );
243 return is_specialized<T, A>() && detail::is_specialized_member_serialize<T, A>();
246 template <
class T,
class A>
247 constexpr
auto is_specialized_member_load() ->
bool
249 static_assert( (is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>() && has_member_load<T, A>())
250 || !(is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>()),
251 "cereal detected member load specialization but no member load function" );
252 return is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>();
255 template <
class T,
class A>
256 constexpr
auto is_specialized_member_save() ->
bool
258 static_assert( (is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>() && has_member_save<T, A>())
259 || !(is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>()),
260 "cereal detected member save specialization but no member save function" );
261 return is_specialized<T, A>() && detail::is_specialized_member_load_save<T, A>();
264 template <
class T,
class A>
265 constexpr
auto is_specialized_non_member_serialize() ->
bool
267 static_assert( (is_specialized<T, A>() && detail::is_specialized_non_member_serialize<T, A>() && has_non_member_serialize<T, A>())
268 || !(is_specialized<T, A>() && detail::is_specialized_non_member_serialize<T, A>()),
269 "cereal detected non-member serialization specialization but no non-member serialize function" );
270 return is_specialized<T, A>() && detail::is_specialized_non_member_serialize<T, A>();
273 template <
class T,
class A>
274 constexpr
auto is_specialized_non_member_load() ->
bool
276 static_assert( (is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>() && has_non_member_load<T, A>())
277 || !(is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>()),
278 "cereal detected non-member load specialization but no non-member load function" );
279 return is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>();
282 template <
class T,
class A>
283 constexpr
auto is_specialized_non_member_save() ->
bool
285 static_assert( (is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>() && has_non_member_save<T, A>())
286 || !(is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>()),
287 "cereal detected non-member save specialization but no non-member save function" );
288 return is_specialized<T, A>() && detail::is_specialized_non_member_load_save<T, A>();
293 constexpr
size_t sizeof_array(
size_t rank = std::rank<T>::value )
295 return rank == 0 ? 1 : std::extent<T>::value * sizeof_array<typename std::remove_extent<T>::type>( rank - 1 );
301 template <
class T,
typename Enable =
void>
303 {
static constexpr
bool value =
false; };
311 static constexpr
bool value =
sizeof(S) ==
sizeof(uint8_t);
320 hash(std::hash<std::type_index>()(
typeid(T)) ^ (std::hash<void const *>()(t) << 1))
324 {
return (type == other.type) && (ptr == other.ptr); }
326 std::type_index type;
334 using is_empty_class = std::integral_constant<bool, detail::is_empty_class_impl<T>::value>;
357 #define CEREAL_ARCHIVE_RESTRICT(INTYPE, OUTTYPE) \
358 typename std::enable_if<std::is_same<Archive, INTYPE>::value || std::is_same<Archive, OUTTYPE>::value, void>::type
363 template <
class T,
class A,
bool Member = traits::has_member_load_and_allocate<T, A>(),
bool NonMember = traits::has_non_member_load_and_allocate<T, A>()>
366 static_assert( !
sizeof(T),
"Cereal detected both member and non member load_and_allocate functions!" );
367 static T * load_andor_allocate( A & ar )
371 template <
class T,
class A>
372 struct Load<T, A, false, false>
374 static_assert( std::is_default_constructible<T>::value,
375 "Trying to serialize a an object with no default constructor.\n\n"
376 "Types must either be default constructible or define either a member or non member Construct function.\n"
377 "Construct functions generally have the signature:\n\n"
378 "template <class Archive>\n"
379 "static T * load_and_allocate(Archive & ar)\n"
383 " return new T(a);\n"
385 static T * load_andor_allocate( A & ar )
389 template <
class T,
class A>
392 static T * load_andor_allocate( A & ar )
394 return access::load_and_allocate<T>( ar );
398 template <
class T,
class A>
401 static T * load_andor_allocate( A & ar )
409 #endif // CEREAL_DETAILS_TRAITS_HPP_