@@ -152,6 +152,7 @@ struct sequence_conversion_tag { };
152152struct tuple_conversion_tag { };
153153struct described_class_conversion_tag { };
154154struct described_enum_conversion_tag { };
155+ struct optional_conversion_tag { };
155156struct no_conversion_tag { };
156157
157158template <class ... Args>
@@ -216,31 +217,40 @@ template< class T >
216217using described_bases = describe::describe_bases<
217218 T, describe::mod_any_access>;
218219
220+ template < class T >
221+ using library_conversion_category = mp11::mp_cond<
222+ // native conversions (constructors and member functions of value)
223+ std::is_same<T, value>, value_conversion_tag,
224+ std::is_same<T, array>, array_conversion_tag,
225+ std::is_same<T, object>, object_conversion_tag,
226+ std::is_same<T, string>, string_conversion_tag,
227+ std::is_same<T, bool >, bool_conversion_tag,
228+ std::is_arithmetic<T>, number_conversion_tag,
229+ // generic conversions
230+ is_null_like<T>, null_like_conversion_tag,
231+ is_string_like<T>, string_like_conversion_tag,
232+ is_map_like<T>, map_like_conversion_tag,
233+ is_sequence_like<T>, sequence_conversion_tag,
234+ is_tuple_like<T>, tuple_conversion_tag,
235+ is_described_class<T>, described_class_conversion_tag,
236+ is_described_enum<T>, described_enum_conversion_tag,
237+ is_optional_like<T>, optional_conversion_tag,
238+ // failed to find a suitable implementation
239+ mp11::mp_true, no_conversion_tag>;
240+
241+ template < class Ctx , class T , class Dir >
242+ using user_conversion_category = mp11::mp_cond<
243+ // user conversion (via tag_invoke)
244+ has_user_conversion3<Ctx, T, Dir>, full_context_conversion_tag,
245+ has_user_conversion2<Ctx, T, Dir>, context_conversion_tag,
246+ has_user_conversion1<T, Dir>, user_conversion_tag>;
247+
219248template < class Ctx , class T , class Dir >
220249struct conversion_category_impl
221250{
222- using type = mp11::mp_cond<
223- // user conversion (via tag_invoke)
224- has_user_conversion3<Ctx, T, Dir>, full_context_conversion_tag,
225- has_user_conversion2<Ctx, T, Dir>, context_conversion_tag,
226- has_user_conversion1<T, Dir>, user_conversion_tag,
227- // native conversions (constructors and member functions of value)
228- std::is_same<T, value>, value_conversion_tag,
229- std::is_same<T, array>, array_conversion_tag,
230- std::is_same<T, object>, object_conversion_tag,
231- std::is_same<T, string>, string_conversion_tag,
232- std::is_same<T, bool >, bool_conversion_tag,
233- std::is_arithmetic<T>, number_conversion_tag,
234- // generic conversions
235- is_null_like<T>, null_like_conversion_tag,
236- is_string_like<T>, string_like_conversion_tag,
237- is_map_like<T>, map_like_conversion_tag,
238- is_sequence_like<T>, sequence_conversion_tag,
239- is_tuple_like<T>, tuple_conversion_tag,
240- is_described_class<T>, described_class_conversion_tag,
241- is_described_enum<T>, described_enum_conversion_tag,
242- // failed to find a suitable implementation
243- mp11::mp_true, no_conversion_tag>;
251+ using type = mp11::mp_eval_or<
252+ library_conversion_category<T>,
253+ user_conversion_category, Ctx, T, Dir>;
244254};
245255template < class Ctx , class T , class Dir >
246256using conversion_category =
@@ -362,6 +372,13 @@ struct supported_context< std::tuple<Ctxs...>, T, Dir >
362372 }
363373};
364374
375+ template < class T >
376+ using value_result_type = typename std::decay<
377+ decltype ( std::declval<T&>().value() )>::type;
378+
379+ template < class T >
380+ using can_reset = decltype ( std::declval<T&>().reset() );
381+
365382} // namespace detail
366383
367384template <class T >
@@ -425,6 +442,14 @@ struct is_described_enum
425442 : describe::has_describe_enumerators<T>
426443{ };
427444
445+ template <class T >
446+ struct is_optional_like
447+ : mp11::mp_and<
448+ mp11::mp_not<std::is_void<
449+ mp11::mp_eval_or<void , detail::value_result_type, T>>>,
450+ mp11::mp_valid<detail::can_reset, T>>
451+ { };
452+
428453} // namespace json
429454} // namespace boost
430455
0 commit comments