11
11
#include < compare>
12
12
#include < concepts>
13
13
#include < cstdint>
14
+ #include < functional>
14
15
#include < initializer_list>
15
16
#include < tuple>
16
17
#include < type_traits>
17
18
19
+ // clang-format off
20
+
21
+ // Workaround GCC11/12 ICE in sequence concept definition below
22
+ #if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 13)
23
+ #define FLUX_COMPILER_IS_GCC12
24
+ #endif
25
+
18
26
#if defined(__cpp_lib_ranges_zip) && (__cpp_lib_ranges_zip >= 202110L)
19
27
#define FLUX_HAVE_CPP23_TUPLE_COMMON_REF
20
28
#endif
@@ -46,6 +54,9 @@ FLUX_EXPORT
46
54
template <typename T>
47
55
struct sequence_traits ;
48
56
57
+ FLUX_EXPORT
58
+ struct default_sequence_traits ;
59
+
49
60
namespace detail {
50
61
51
62
template <typename T>
@@ -73,29 +84,6 @@ template <has_element_type T>
73
84
requires requires { typename traits_t <T>::value_type; }
74
85
struct value_type <T> { using type = typename traits_t <T>::value_type; };
75
86
76
- template <has_element_type T>
77
- requires requires { traits_t <T>::using_primary_template; } &&
78
- requires { typename T::value_type; }
79
- struct value_type <T> { using type = typename T::value_type; };
80
-
81
- template <has_element_type T>
82
- struct rvalue_element_type {
83
- using type = std::conditional_t <std::is_lvalue_reference_v<element_t <T>>,
84
- std::add_rvalue_reference_t <std::remove_reference_t <element_t <T>>>,
85
- element_t <T>>;
86
- };
87
-
88
- template <typename Seq>
89
- concept has_move_at = requires (Seq& seq, cursor_t <Seq> const & cur) {
90
- { traits_t <Seq>::move_at (seq, cur) };
91
- };
92
-
93
- template <has_element_type T>
94
- requires has_move_at<T>
95
- struct rvalue_element_type <T> {
96
- using type = decltype(traits_t <T>::move_at(FLUX_DECLVAL(T&), FLUX_DECLVAL(cursor_t <T> const &)));
97
- };
98
-
99
87
} // namespace detail
100
88
101
89
FLUX_EXPORT
@@ -110,7 +98,7 @@ using index_t = flux::config::int_type;
110
98
111
99
FLUX_EXPORT
112
100
template <typename Seq>
113
- using rvalue_element_t = typename detail::rvalue_element_type <Seq>::type ;
101
+ using rvalue_element_t = decltype( detail::traits_t <Seq>::move_at(FLUX_DECLVAL(Seq&), FLUX_DECLVAL( cursor_t <Seq> const &))) ;
114
102
115
103
FLUX_EXPORT
116
104
template <typename Seq>
@@ -136,7 +124,7 @@ template <typename T>
136
124
concept can_reference = requires { typename with_ref<T>; };
137
125
138
126
template <typename Seq, typename Traits = sequence_traits<std::remove_cvref_t <Seq>>>
139
- concept sequence_concept =
127
+ concept sequence_requirements =
140
128
requires (Seq& seq) {
141
129
{ Traits::first (seq) } -> cursor;
142
130
} &&
@@ -146,7 +134,21 @@ concept sequence_concept =
146
134
} &&
147
135
requires (Seq& seq, cursor_t <Seq>& cur) {
148
136
{ Traits::inc (seq, cur) };
137
+ };
138
+
139
+ template <typename Seq, typename Traits = sequence_traits<std::remove_cvref_t <Seq>>>
140
+ concept sequence_concept =
141
+ sequence_requirements<Seq> &&
142
+ requires (Seq& seq, cursor_t <Seq> const & cur) {
143
+ { Traits::read_at_unchecked (seq, cur) } -> std::same_as<element_t <Seq>>;
144
+ { Traits::move_at (seq, cur) } -> can_reference;
145
+ { Traits::move_at_unchecked (seq, cur) } -> std::same_as<rvalue_element_t <Seq>>;
146
+ } &&
147
+ #ifndef FLUX_COMPILER_IS_GCC12
148
+ requires (Seq& seq, bool (*pred)(element_t <Seq>)) {
149
+ { Traits::for_each_while (seq, pred) } -> std::same_as<cursor_t <Seq>>;
149
150
} &&
151
+ #endif
150
152
#ifdef FLUX_HAVE_CPP23_TUPLE_COMMON_REF
151
153
std::common_reference_with<element_t <Seq>&&, value_t <Seq>&> &&
152
154
std::common_reference_with<rvalue_element_t <Seq>&&, value_t <Seq> const &> &&
@@ -180,8 +182,7 @@ concept multipass_sequence =
180
182
namespace detail {
181
183
182
184
template <typename Seq, typename Traits = sequence_traits<std::remove_cvref_t <Seq>>>
183
- concept bidirectional_sequence_concept =
184
- multipass_sequence<Seq> &&
185
+ concept bidirectional_sequence_requirements =
185
186
requires (Seq& seq, cursor_t <Seq>& cur) {
186
187
{ Traits::dec (seq, cur) };
187
188
};
@@ -190,13 +191,13 @@ concept bidirectional_sequence_concept =
190
191
191
192
FLUX_EXPORT
192
193
template <typename Seq>
193
- concept bidirectional_sequence = detail::bidirectional_sequence_concept <Seq>;
194
+ concept bidirectional_sequence = multipass_sequence<Seq> && detail::bidirectional_sequence_requirements <Seq>;
194
195
195
196
namespace detail {
196
197
197
198
template <typename Seq, typename Traits = sequence_traits<std::remove_cvref_t <Seq>>>
198
- concept random_access_sequence_concept =
199
- bidirectional_sequence<Seq> && ordered_cursor<cursor_t <Seq>> &&
199
+ concept random_access_sequence_requirements =
200
+ ordered_cursor<cursor_t <Seq>> &&
200
201
requires (Seq& seq, cursor_t <Seq>& cur, distance_t offset) {
201
202
{ Traits::inc (seq, cur, offset) };
202
203
} &&
@@ -208,13 +209,14 @@ concept random_access_sequence_concept =
208
209
209
210
FLUX_EXPORT
210
211
template <typename Seq>
211
- concept random_access_sequence = detail::random_access_sequence_concept<Seq>;
212
+ concept random_access_sequence =
213
+ bidirectional_sequence<Seq> &&
214
+ detail::random_access_sequence_requirements<Seq>;
212
215
213
216
namespace detail {
214
217
215
218
template <typename Seq, typename Traits = sequence_traits<std::remove_cvref_t <Seq>>>
216
- concept bounded_sequence_concept =
217
- sequence<Seq> &&
219
+ concept bounded_sequence_requirements =
218
220
requires (Seq& seq) {
219
221
{ Traits::last (seq) } -> std::same_as<cursor_t <Seq>>;
220
222
};
@@ -223,14 +225,12 @@ concept bounded_sequence_concept =
223
225
224
226
FLUX_EXPORT
225
227
template <typename Seq>
226
- concept bounded_sequence = detail::bounded_sequence_concept <Seq>;
228
+ concept bounded_sequence = sequence<Seq> && detail::bounded_sequence_requirements <Seq>;
227
229
228
230
namespace detail {
229
231
230
232
template <typename Seq, typename Traits = sequence_traits<std::remove_cvref_t <Seq>>>
231
- concept contiguous_sequence_concept =
232
- random_access_sequence<Seq> &&
233
- bounded_sequence<Seq> &&
233
+ concept contiguous_sequence_requirements =
234
234
std::is_lvalue_reference_v<element_t <Seq>> &&
235
235
std::same_as<value_t <Seq>, std::remove_cvref_t <element_t <Seq>>> &&
236
236
requires (Seq& seq) {
@@ -241,24 +241,24 @@ concept contiguous_sequence_concept =
241
241
242
242
FLUX_EXPORT
243
243
template <typename Seq>
244
- concept contiguous_sequence = detail::contiguous_sequence_concept<Seq>;
244
+ concept contiguous_sequence =
245
+ random_access_sequence<Seq> &&
246
+ bounded_sequence<Seq> &&
247
+ detail::contiguous_sequence_requirements<Seq>;
245
248
246
249
namespace detail {
247
250
248
251
template <typename Seq, typename Traits = sequence_traits<std::remove_cvref_t <Seq>>>
249
- concept sized_sequence_concept =
250
- sequence<Seq> &&
251
- (requires (Seq& seq) {
252
+ concept sized_sequence_requirements =
253
+ requires (Seq& seq) {
252
254
{ Traits::size (seq) } -> std::convertible_to<distance_t >;
253
- } || (
254
- random_access_sequence<Seq> && bounded_sequence<Seq>
255
- ));
255
+ };
256
256
257
257
} // namespace detail
258
258
259
259
FLUX_EXPORT
260
260
template <typename Seq>
261
- concept sized_sequence = detail::sized_sequence_concept <Seq>;
261
+ concept sized_sequence = sequence<Seq> && detail::sized_sequence_requirements <Seq>;
262
262
263
263
FLUX_EXPORT
264
264
template <typename Seq, typename T>
@@ -366,6 +366,77 @@ concept derived_from_inline_sequence_base = requires(T t) {
366
366
/*
367
367
* Default sequence_traits implementation
368
368
*/
369
+
370
+ struct default_sequence_traits {
371
+
372
+ template <typename Self>
373
+ requires detail::sequence_requirements<Self>
374
+ static constexpr auto read_at_unchecked (Self& self, cursor_t <Self> const & cur)
375
+ -> decltype(detail::traits_t <Self>::read_at(self, cur))
376
+ {
377
+ return detail::traits_t <Self>::read_at (self, cur);
378
+ }
379
+
380
+ template <typename Self>
381
+ requires detail::sequence_requirements<Self>
382
+ static constexpr auto move_at (Self& self, cursor_t <Self> const & cur)
383
+ -> std::conditional_t<std::is_lvalue_reference_v<element_t<Self>>,
384
+ std::add_rvalue_reference_t<std::remove_reference_t<element_t<Self>>>,
385
+ element_t<Self>>
386
+ {
387
+ using Traits = detail::traits_t <Self>;
388
+ if constexpr (std::is_lvalue_reference_v<element_t <Self>>) {
389
+ return std::move (Traits::read_at (self, cur));
390
+ } else {
391
+ return Traits::read_at (self, cur);
392
+ }
393
+ }
394
+
395
+ template <typename Self>
396
+ requires detail::sequence_requirements<Self>
397
+ static constexpr auto move_at_unchecked (Self& self, cursor_t <Self> const & cur)
398
+ -> decltype(detail::traits_t <Self>::move_at(self, cur))
399
+ {
400
+ return detail::traits_t <Self>::move_at (self, cur);
401
+ }
402
+
403
+ template <typename Self>
404
+ requires detail::random_access_sequence_requirements<Self> &&
405
+ detail::bounded_sequence_requirements<Self>
406
+ static constexpr auto size (Self& self) -> distance_t
407
+ {
408
+ using Traits = detail::traits_t <Self>;
409
+ return Traits::distance (self, Traits::first (self), Traits::last (self));
410
+ }
411
+
412
+ template <typename Self, typename Pred>
413
+ requires detail::sequence_requirements<Self>
414
+ static constexpr auto for_each_while (Self& self, Pred&& pred) -> cursor_t<Self>
415
+ {
416
+ using Traits = detail::traits_t <Self>;
417
+
418
+ auto cur = Traits::first (self);
419
+ if constexpr (bounded_sequence<Self> && regular_cursor<cursor_t <Self>>) {
420
+ auto const last = Traits::last (self);
421
+ while (cur != last) {
422
+ if (!std::invoke (pred, Traits::read_at (self, cur))) {
423
+ break ;
424
+ }
425
+ Traits::inc (self, cur);
426
+ }
427
+ } else {
428
+ while (!Traits::is_last (self, cur)) {
429
+ if (!std::invoke (pred, Traits::read_at (self, cur))) {
430
+ break ;
431
+ }
432
+ Traits::inc (self, cur);
433
+ }
434
+ }
435
+ return cur;
436
+ }
437
+
438
+ };
439
+
369
440
namespace detail {
370
441
371
442
template <typename T>
0 commit comments