Skip to content

Commit bde2641

Browse files
committed
Remove variant_has_substitute
1 parent d2dca4b commit bde2641

7 files changed

Lines changed: 80 additions & 114 deletions

File tree

‎include/iris/x4/core/detail/parse_alternative.hpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ template<class Parser, X4Attribute Attr>
6767
struct pass_parser_attribute
6868
{
6969
using attribute_type = parser_traits<Parser>::attribute_type;
70-
using substitute_type = traits::variant_find_substitute_t<Attr, attribute_type>;
70+
using substitute_type = traits::variant_find_holdable_type_t<Attr, attribute_type>;
7171

7272
using type = std::conditional_t<
7373
std::same_as<Attr, substitute_type>,

‎include/iris/x4/core/detail/parse_into_container.hpp‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,12 @@ template<class Parser>
140140
requires Parser::handles_container
141141
struct parse_into_container_impl<Parser>
142142
{
143+
// TODO: decompose pass_attribute_as_is to make more logic clear
143144
template<std::forward_iterator It, std::sentinel_for<It> Se, class Context, X4Attribute Attr>
144145
static constexpr bool pass_attibute_as_is = std::disjunction_v<
145146
parser_accepts_container<Parser, Attr>,
146147

147-
std::negation<traits::can_hold<
148+
std::negation<std::is_same<
148149
typename traits::pseudo_attribute<
149150
It, Se, Context,
150151
typename parser_traits<Parser>::attribute_type
@@ -217,7 +218,7 @@ parse_into_container(
217218
using attribute_type = parser_traits<Parser>::attribute_type;
218219

219220
// e.g. `std::string` when the attribute_type is `char`
220-
using substitute_type = traits::variant_find_substitute_t<Attr, traits::build_container_t<attribute_type>>;
221+
using substitute_type = traits::variant_find_holdable_type_t<Attr, traits::build_container_t<attribute_type>>;
221222

222223
// instead of creating a temporary `substitute_type`, append directly into the emplaced alternative
223224
auto& variant_alt = attr.template emplace<substitute_type>();

‎include/iris/x4/core/move_to.hpp‎

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -153,51 +153,32 @@ move_to(Source&& src, Dest& dest)
153153
}
154154

155155
template<traits::NonUnusedAttr Source, traits::CategorizedAttr<traits::variant_attr> Dest>
156-
requires traits::is_size_one_sequence_v<Source> && traits::variant_has_substitute_v<Dest, Source>
156+
requires std::is_assignable_v<Dest&, Source&&>
157157
constexpr void
158158
move_to(Source&& src, Dest& dest)
159159
noexcept(std::is_nothrow_assignable_v<Dest&, Source&&>)
160160
{
161161
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
162162

163-
// dest is a variant, src is a single element tuple-like that the variant
164-
// *can* directly hold.
165-
static_assert(std::is_assignable_v<Dest&, Source>);
166163
dest = std::forward<Source>(src);
167164
}
168165

169166
template<traits::NonUnusedAttr Source, traits::CategorizedAttr<traits::variant_attr> Dest>
170-
requires traits::is_size_one_sequence_v<Source> && (!traits::variant_has_substitute_v<Dest, Source>)
167+
requires (!std::is_assignable_v<Dest&, Source&&>) && traits::is_size_one_sequence_v<Source>
171168
constexpr void
172169
move_to(Source&& src, Dest& dest)
173170
noexcept(noexcept(dest = std::forward_like<Source>(alloy::get<0>(std::forward<Source>(src)))))
174171
{
175172
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
176173

177-
// dest is a variant, src is a single element tuple-like that the variant
178-
// cannot directly hold. We'll try to unwrap the single element tuple-like.
179-
180-
// Make sure that the Dest variant can really hold Source
181174
static_assert(
182-
traits::variant_has_substitute_v<Dest, alloy::tuple_element_t<0, Source>>,
175+
std::is_assignable_v<Dest&, decltype(std::forward_like<Source>(alloy::get<0>(std::forward<Source>(src))))>,
183176
"Error! The destination variant (Dest) cannot hold the source type (Source)"
184177
);
185178

186-
// TODO: preliminarily invoke static_assert to check if the assignment is valid
187179
dest = std::forward_like<Source>(alloy::get<0>(std::forward<Source>(src)));
188180
}
189181

190-
template<traits::NonUnusedAttr Source, traits::CategorizedAttr<traits::variant_attr> Dest>
191-
requires (!traits::is_size_one_sequence_v<Source>)
192-
constexpr void
193-
move_to(Source&& src, Dest& dest)
194-
noexcept(std::is_nothrow_assignable_v<Dest&, Source&&>)
195-
{
196-
static_assert(!std::same_as<std::remove_cvref_t<Source>, Dest>, "[BUG] This call should instead resolve to the overload handling identical types");
197-
static_assert(std::is_assignable_v<Dest&, Source>);
198-
dest = std::forward<Source>(src);
199-
}
200-
201182
template<traits::NonUnusedAttr Source, traits::CategorizedAttr<traits::optional_attr> Dest>
202183
constexpr void
203184
move_to(Source&& src, Dest& dest)

‎include/iris/x4/traits/can_hold.hpp‎

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,23 @@
1010
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1111
=============================================================================*/
1212

13-
#include <iris/x4/core/attribute.hpp>
1413
#include <iris/x4/traits/container_traits.hpp>
1514
#include <iris/x4/traits/tuple_traits.hpp>
1615

16+
#include <iris/x4/core/attribute.hpp>
17+
1718
#include <iris/alloy/traits.hpp>
1819

1920
#include <optional>
2021
#include <type_traits>
2122

2223
namespace iris::x4::traits {
2324

24-
// Find out if T can be a (strong) substitute for Attribute
25-
template<class T, class Attr>
25+
template<class T, class U>
2626
struct can_hold;
2727

28-
template<class T, class Attr>
29-
constexpr bool can_hold_v = can_hold<T, Attr>::value;
30-
31-
template<class T>
32-
struct is_variant;
33-
34-
template<class Variant, class Attr>
35-
struct variant_has_substitute;
28+
template<class T, class U>
29+
constexpr bool can_hold_v = can_hold<T, U>::value;
3630

3731
namespace detail {
3832

@@ -50,55 +44,50 @@ template<class TTuple, class UTuple>
5044
requires is_same_size_sequence_v<TTuple, UTuple>
5145
struct is_all_substitute_for_tuple<TTuple, UTuple> : is_all_substitute_for_tuple_impl<TTuple, UTuple> {};
5246

53-
template<class T, class Attr>
47+
template<class T, class U>
5448
struct value_type_can_hold
55-
: can_hold<container_value_t<T>, container_value_t<Attr>>
49+
: can_hold<container_value_t<T>, container_value_t<U>>
5650
{};
5751

58-
template<class T, class Attr>
52+
template<class T, class U>
5953
struct can_hold_impl : std::false_type {};
6054

61-
template<class T, class Attr>
55+
template<class T, class U>
6256
requires std::conjunction_v<
6357
alloy::is_tuple_like<T>,
64-
alloy::is_tuple_like<Attr>
58+
alloy::is_tuple_like<U>
6559
>
66-
struct can_hold_impl<T, Attr>
67-
: is_all_substitute_for_tuple<T, Attr>
60+
struct can_hold_impl<T, U>
61+
: is_all_substitute_for_tuple<T, U>
6862
{};
6963

70-
template<class T, class Attr>
64+
template<class T, class U>
7165
requires
7266
is_container_v<T> &&
73-
is_container_v<Attr>
74-
struct can_hold_impl<T, Attr>
75-
: value_type_can_hold<T, Attr>
76-
{};
77-
78-
template<class T, class Attr>
79-
requires is_variant<T>::value
80-
struct can_hold_impl<T, Attr>
81-
: variant_has_substitute<T, Attr>
67+
is_container_v<U>
68+
struct can_hold_impl<T, U>
69+
: value_type_can_hold<T, U>
8270
{};
8371

8472
} // detail
8573

86-
template<class T, class Attr>
74+
template<class T, class U>
8775
struct can_hold
8876
: std::disjunction<
89-
std::is_same<T, Attr>,
90-
detail::can_hold_impl<T, Attr>
77+
std::is_same<T, U>,
78+
std::is_assignable<T&, U>,
79+
detail::can_hold_impl<T, U>
9180
>
9281
{};
9382

94-
template<class T, X4UnusedAttribute Attr>
95-
struct can_hold<T, Attr>
83+
template<class T, X4UnusedAttribute U>
84+
struct can_hold<T, U>
9685
: std::false_type
9786
{};
9887

99-
template<class T, X4Attribute Attr>
100-
struct can_hold<std::optional<T>, std::optional<Attr>>
101-
: can_hold<T, Attr>
88+
template<class T, class U>
89+
struct can_hold<std::optional<T>, std::optional<U>>
90+
: can_hold<T, U>
10291
{};
10392

10493
} // iris::x4::traits

‎include/iris/x4/traits/variant_traits.hpp‎

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <iris/rvariant/variant_helper.hpp>
1818

19+
#include <concepts>
1920
#include <type_traits>
2021

2122
namespace iris::x4::traits {
@@ -34,20 +35,43 @@ struct is_variant<iris::rvariant<Ts...>> : std::true_type {};
3435

3536
namespace 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

7094
template<class Variant, class T>
71-
struct variant_find_substitute;
95+
struct variant_find_holdable_type;
7296

7397
template<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

76100
template<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

‎test/x4/alternative.cpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ TEST_CASE("alternative")
231231
using attribute_type = x4::parser_traits<Parser>::attribute_type;
232232
STATIC_CHECK(std::same_as<attribute_type, std::vector<bool>>);
233233

234-
using substitute_type = x4::traits::variant_find_substitute_t<Attr, attribute_type>;
234+
using substitute_type = x4::traits::variant_find_holdable_type_t<Attr, attribute_type>;
235235
STATIC_CHECK(std::same_as<substitute_type, std::vector<bool>>);
236236

237237
Attr var;
@@ -245,7 +245,7 @@ TEST_CASE("alternative")
245245
using attribute_type = x4::parser_traits<Parser>::attribute_type;
246246
STATIC_CHECK(std::same_as<attribute_type, std::string>);
247247

248-
using substitute_type = x4::traits::variant_find_substitute_t<Attr, attribute_type>;
248+
using substitute_type = x4::traits::variant_find_holdable_type_t<Attr, attribute_type>;
249249
STATIC_CHECK(std::same_as<substitute_type, std::string>);
250250

251251
Attr var;

‎test/x4/substitution.cpp‎

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,3 @@ TEST_CASE("can_hold")
1313
STATIC_CHECK( x4::traits::can_hold_v<iris::rvariant<int, double>, int>);
1414
STATIC_CHECK(!x4::traits::can_hold_v<int, iris::rvariant<int, double>>);
1515
}
16-
17-
TEST_CASE("variant_has_substitute")
18-
{
19-
STATIC_CHECK( x4::traits::variant_has_substitute_v<iris::rvariant<int, double>, int>);
20-
STATIC_CHECK(!x4::traits::variant_has_substitute_v<iris::rvariant<int, double>, char>);
21-
}

0 commit comments

Comments
 (0)