@@ -152,6 +152,7 @@ struct sequence_conversion_tag { };
152152struct tuple_conversion_tag { };
153153struct described_class_conversion_tag { };
154154struct described_enum_conversion_tag { };
155+ struct variant_conversion_tag { };
155156struct optional_conversion_tag { };
156157struct no_conversion_tag { };
157158
@@ -217,40 +218,55 @@ template< class T >
217218using described_bases = describe::describe_bases<
218219 T, describe::mod_any_access>;
219220
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-
221+ // user conversion (via tag_invoke)
241222template < class Ctx , class T , class Dir >
242223using user_conversion_category = mp11::mp_cond<
243- // user conversion (via tag_invoke)
244224 has_user_conversion3<Ctx, T, Dir>, full_context_conversion_tag,
245225 has_user_conversion2<Ctx, T, Dir>, context_conversion_tag,
246226 has_user_conversion1<T, Dir>, user_conversion_tag>;
247227
228+ // native conversions (constructors and member functions of value)
229+ template < class T >
230+ using native_conversion_category = mp11::mp_cond<
231+ std::is_same<T, value>, value_conversion_tag,
232+ std::is_same<T, array>, array_conversion_tag,
233+ std::is_same<T, object>, object_conversion_tag,
234+ std::is_same<T, string>, string_conversion_tag>;
235+
236+ // generic conversions
237+ template < class T >
238+ using generic_conversion_category = mp11::mp_cond<
239+ std::is_same<T, bool >, bool_conversion_tag,
240+ std::is_arithmetic<T>, number_conversion_tag,
241+ is_null_like<T>, null_like_conversion_tag,
242+ is_string_like<T>, string_like_conversion_tag,
243+ is_map_like<T>, map_like_conversion_tag,
244+ is_sequence_like<T>, sequence_conversion_tag,
245+ is_tuple_like<T>, tuple_conversion_tag,
246+ is_described_class<T>, described_class_conversion_tag,
247+ is_described_enum<T>, described_enum_conversion_tag,
248+ is_variant_like<T>, variant_conversion_tag,
249+ is_optional_like<T>, optional_conversion_tag,
250+ // failed to find a suitable implementation
251+ mp11::mp_true, no_conversion_tag>;
252+
253+ template < class T >
254+ using nested_type = typename T::type;
255+ template < class T1 , class T2 >
256+ using conversion_category_impl_helper = mp11::mp_eval_if_not<
257+ std::is_same<detail::no_conversion_tag, T1>,
258+ T1,
259+ mp11::mp_eval_or_q, T1, mp11::mp_quote<nested_type>, T2>;
248260template < class Ctx , class T , class Dir >
249261struct conversion_category_impl
250262{
251- using type = mp11::mp_eval_or<
252- library_conversion_category<T>,
253- user_conversion_category, Ctx, T, Dir>;
263+ using type = mp11::mp_fold<
264+ mp11::mp_list<
265+ mp11::mp_defer<user_conversion_category, Ctx, T, Dir>,
266+ mp11::mp_defer<native_conversion_category, T>,
267+ mp11::mp_defer<generic_conversion_category, T>>,
268+ no_conversion_tag,
269+ conversion_category_impl_helper>;
254270};
255271template < class Ctx , class T , class Dir >
256272using conversion_category =
@@ -379,6 +395,10 @@ using value_result_type = typename std::decay<
379395template < class T >
380396using can_reset = decltype ( std::declval<T&>().reset() );
381397
398+ template < class T >
399+ using has_valueless_by_exception =
400+ decltype ( std::declval<T const &>().valueless_by_exception() );
401+
382402} // namespace detail
383403
384404template <class T >
@@ -442,6 +462,10 @@ struct is_described_enum
442462 : describe::has_describe_enumerators<T>
443463{ };
444464
465+ template <class T >
466+ struct is_variant_like : mp11::mp_valid<detail::has_valueless_by_exception, T>
467+ { };
468+
445469template <class T >
446470struct is_optional_like
447471 : mp11::mp_and<
0 commit comments