1616
1717#include < iris/rvariant/variant_helper.hpp>
1818
19+ #include < concepts>
1920#include < type_traits>
2021
2122namespace iris ::x4::traits {
@@ -34,20 +35,43 @@ struct is_variant<iris::rvariant<Ts...>> : std::true_type {};
3435
3536namespace detail {
3637
37- template <class Attr , class ... Ts>
38- struct variant_find_substitute_impl ;
38+ template <class T , class ... Ts>
39+ struct variant_has_exact_type ;
3940
40- template <class Attr >
41- struct variant_find_substitute_impl <Attr>
41+ template <class T , class ... Ts>
42+ inline constexpr bool variant_has_exact_type_v = variant_has_exact_type<T, Ts...>::value;
43+
44+ template <class T >
45+ struct variant_has_exact_type <T>
46+ : std::false_type
47+ {};
48+
49+ template <class T , class First , class ... Rest>
50+ requires std::same_as<T, iris::unwrap_recursive_type<First>>
51+ struct variant_has_exact_type <T, First, Rest...>
52+ : std::true_type
53+ {};
54+
55+ template <class T , class First , class ... Rest>
56+ requires (!std::same_as<T, iris::unwrap_recursive_type<First>>)
57+ struct variant_has_exact_type <T, First, Rest...>
58+ : variant_has_exact_type<T, Rest...>
59+ {};
60+
61+ template <class T , class ... Ts>
62+ struct variant_find_holdable_type_impl ;
63+
64+ template <class T >
65+ struct variant_find_holdable_type_impl <T>
4266{
43- using type = Attr ;
67+ using type = T ;
4468};
4569
46- template <class Attr , class First , class ... Rest>
47- struct variant_find_substitute_impl <Attr , First, Rest...>
70+ template <class T , class First , class ... Rest>
71+ struct variant_find_holdable_type_impl <T , First, Rest...>
4872{
4973 using type = std::conditional_t <
50- can_hold_v<iris::unwrap_recursive_type<First>, Attr >,
74+ can_hold_v<iris::unwrap_recursive_type<First>, T >,
5175
5276 // Given some type `T`, when both `T` and `recursive_wrapper<T>` is seen
5377 // during attribute resolution, X4 should ideally materialize the latter
@@ -60,61 +84,38 @@ struct variant_find_substitute_impl<Attr, First, Rest...>
6084 //
6185 First, // no need to unwrap due to the reason described above
6286
63- typename variant_find_substitute_impl<Attr , Rest...>::type
87+ typename variant_find_holdable_type_impl<T , Rest...>::type
6488 >;
6589};
6690
6791} // detail
6892
6993
7094template <class Variant , class T >
71- struct variant_find_substitute ;
95+ struct variant_find_holdable_type ;
7296
7397template <class Variant , class T >
74- using variant_find_substitute_t = typename variant_find_substitute <Variant, T>::type;
98+ using variant_find_holdable_type_t = typename variant_find_holdable_type <Variant, T>::type;
7599
76100template <class Variant >
77- struct variant_find_substitute <Variant, Variant>
101+ struct variant_find_holdable_type <Variant, Variant>
78102{
79103 using type = Variant;
80104};
81105
82- template <class ... Ts, class U >
83- requires (!std::same_as<iris::rvariant<Ts...>, U>)
84- struct variant_find_substitute <iris::rvariant<Ts...>, U >
106+ template <class ... Ts, class T >
107+ requires (!std::same_as<iris::rvariant<Ts...>, T>) && detail::variant_has_exact_type_v<T, Ts...>
108+ struct variant_find_holdable_type <iris::rvariant<Ts...>, T >
85109{
86- using type = typename detail::variant_find_substitute_impl<U, Ts...>::type ;
110+ using type = T ;
87111};
88112
89-
90- template <class Variant , class U >
91- struct variant_has_substitute ;
92-
93- template <class Variant , class U >
94- constexpr bool variant_has_substitute_v = variant_has_substitute<Variant, U>::value;
95-
96- template <class Variant >
97- struct variant_has_substitute <Variant, Variant>
98- : std::true_type
99- {};
100-
101- template <class T >
102- struct variant_has_substitute <unused_type, T>
103- : std::true_type
104- {};
105-
106- template <class T >
107- struct variant_has_substitute <unused_type const , T>
108- : std::true_type
109- {};
110-
111- // Recursively find the first type from the variant that can be a substitute for `T`.
112- // Returns boolean value whether it was found.
113- template <class ... Ts, class U >
114- requires (!std::same_as<iris::rvariant<Ts...>, U>)
115- struct variant_has_substitute <iris::rvariant<Ts...>, U>
116- : std::disjunction<can_hold<Ts, U>...>
117- {};
113+ template <class ... Ts, class T >
114+ requires (!std::same_as<iris::rvariant<Ts...>, T>) && (!detail::variant_has_exact_type_v<T, Ts...>)
115+ struct variant_find_holdable_type <iris::rvariant<Ts...>, T>
116+ {
117+ using type = typename detail::variant_find_holdable_type_impl<T, Ts...>::type;
118+ };
118119
119120} // iris::x4::traits
120121
0 commit comments