30 #ifndef _RANGES_UTIL_H
31 #define _RANGES_UTIL_H 1
33 #if __cplusplus > 201703L
36 #ifdef __cpp_lib_ranges
37 namespace std _GLIBCXX_VISIBILITY(default)
39 _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 template<
typename _Range>
47 concept __simple_view = view<_Range> && range<const _Range>
48 && same_as<iterator_t<_Range>, iterator_t<const _Range>>
49 && same_as<sentinel_t<_Range>, sentinel_t<const _Range>>;
51 template<
typename _It>
52 concept __has_arrow = input_iterator<_It>
53 && (is_pointer_v<_It> || requires(_It __it) { __it.operator->(); });
55 template<
typename _Tp,
typename _Up>
57 = !same_as<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
61 template<
typename _Derived>
62 requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
63 class view_interface :
public view_base
66 constexpr _Derived& _M_derived() noexcept
68 static_assert(derived_from<_Derived, view_interface<_Derived>>);
69 static_assert(view<_Derived>);
70 return static_cast<_Derived&
>(*this);
73 constexpr
const _Derived& _M_derived() const noexcept
75 static_assert(derived_from<_Derived, view_interface<_Derived>>);
76 static_assert(view<_Derived>);
77 return static_cast<const _Derived&
>(*this);
82 empty() requires forward_range<_Derived>
86 empty() const requires forward_range<const _Derived>
90 operator bool() requires requires {
ranges::empty(_M_derived()); }
94 operator bool() const requires requires {
ranges::empty(_M_derived()); }
98 data() requires contiguous_iterator<iterator_t<_Derived>>
103 requires range<const _Derived>
104 && contiguous_iterator<iterator_t<const _Derived>>
109 requires forward_range<_Derived>
110 && sized_sentinel_for<sentinel_t<_Derived>, iterator_t<_Derived>>
115 requires forward_range<const _Derived>
116 && sized_sentinel_for<sentinel_t<const _Derived>,
117 iterator_t<const _Derived>>
120 constexpr decltype(
auto)
121 front() requires forward_range<_Derived>
123 __glibcxx_assert(!
empty());
127 constexpr decltype(
auto)
128 front() const requires forward_range<const _Derived>
130 __glibcxx_assert(!
empty());
134 constexpr decltype(
auto)
136 requires bidirectional_range<_Derived> && common_range<_Derived>
138 __glibcxx_assert(!
empty());
142 constexpr decltype(
auto)
144 requires bidirectional_range<const _Derived>
145 && common_range<const _Derived>
147 __glibcxx_assert(!
empty());
151 template<random_access_range _Range = _Derived>
152 constexpr decltype(
auto)
153 operator[](range_difference_t<_Range> __n)
156 template<random_access_range _Range = const _Derived>
157 constexpr decltype(
auto)
158 operator[](range_difference_t<_Range> __n)
const
164 template<
class _From,
class _To>
165 concept __convertible_to_non_slicing = convertible_to<_From, _To>
166 && !(is_pointer_v<decay_t<_From>> && is_pointer_v<decay_t<_To>>
167 && __not_same_as<remove_pointer_t<decay_t<_From>>,
168 remove_pointer_t<decay_t<_To>>>);
170 template<
typename _Tp>
172 = !is_reference_v<_Tp> && requires(_Tp __t)
174 typename tuple_size<_Tp>::type;
175 requires derived_from<tuple_size<_Tp>, integral_constant<size_t, 2>>;
176 typename tuple_element_t<0, remove_const_t<_Tp>>;
177 typename tuple_element_t<1, remove_const_t<_Tp>>;
178 { get<0>(__t) } -> convertible_to<
const tuple_element_t<0, _Tp>&>;
179 { get<1>(__t) } -> convertible_to<
const tuple_element_t<1, _Tp>&>;
182 template<
typename _Tp,
typename _Up,
typename _Vp>
183 concept __pair_like_convertible_from
184 = !range<_Tp> && __pair_like<_Tp>
185 && constructible_from<_Tp, _Up, _Vp>
186 && __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>>
187 && convertible_to<_Vp, tuple_element_t<1, _Tp>>;
191 enum class subrange_kind : bool { unsized, sized };
194 template<input_or_output_iterator _It, sentinel_for<_It> _Sent = _It,
195 subrange_kind _Kind = sized_sentinel_for<_Sent, _It>
196 ? subrange_kind::sized : subrange_kind::unsized>
197 requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>)
198 class subrange : public view_interface<subrange<_It, _Sent, _Kind>>
202 static const bool _S_store_size
203 = _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>;
205 _It _M_begin = _It();
206 [[no_unique_address]] _Sent _M_end = _Sent();
209 = __detail::__make_unsigned_like_t<iter_difference_t<_It>>;
211 template<
typename,
bool = _S_store_size>
215 template<
typename _Tp>
216 struct _Size<_Tp, true>
219 [[no_unique_address]] _Size<__size_type> _M_size = {};
222 subrange() =
default;
225 subrange(__detail::__convertible_to_non_slicing<_It>
auto __i, _Sent __s)
226 requires (!_S_store_size)
227 : _M_begin(std::
move(__i)), _M_end(__s)
231 subrange(__detail::__convertible_to_non_slicing<_It>
auto __i, _Sent __s,
233 requires (_Kind == subrange_kind::sized)
234 : _M_begin(std::
move(__i)), _M_end(__s)
236 if constexpr (_S_store_size)
237 _M_size._M_size = __n;
240 template<__detail::__not_same_as<subrange> _Rng>
241 requires borrowed_range<_Rng>
242 && __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
243 && convertible_to<sentinel_t<_Rng>, _Sent>
245 subrange(_Rng&& __r) requires _S_store_size && sized_range<_Rng>
246 : subrange(__r, ranges::
size(__r))
249 template<__detail::__not_same_as<subrange> _Rng>
250 requires borrowed_range<_Rng>
251 && __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
252 && convertible_to<sentinel_t<_Rng>, _Sent>
254 subrange(_Rng&& __r) requires (!_S_store_size)
255 : subrange(ranges::
begin(__r), ranges::
end(__r))
258 template<borrowed_range _Rng>
259 requires __detail::__convertible_to_non_slicing<iterator_t<_Rng>, _It>
260 && convertible_to<sentinel_t<_Rng>, _Sent>
262 subrange(_Rng&& __r, __size_type __n)
263 requires (_Kind == subrange_kind::sized)
267 template<__detail::__not_same_as<subrange> _PairLike>
268 requires __detail::__pair_like_convertible_from<_PairLike,
const _It&,
271 operator _PairLike()
const
272 {
return _PairLike(_M_begin, _M_end); }
275 begin() const requires copyable<_It>
278 [[nodiscard]] constexpr _It
279 begin() requires (!copyable<_It>)
282 constexpr _Sent
end()
const {
return _M_end; }
284 constexpr
bool empty()
const {
return _M_begin == _M_end; }
286 constexpr __size_type
287 size() const requires (_Kind == subrange_kind::sized)
289 if constexpr (_S_store_size)
290 return _M_size._M_size;
292 return __detail::__to_unsigned_like(_M_end - _M_begin);
295 [[nodiscard]] constexpr subrange
296 next(iter_difference_t<_It> __n = 1) const &
297 requires forward_iterator<_It>
304 [[nodiscard]] constexpr subrange
305 next(iter_difference_t<_It> __n = 1) &&
311 [[nodiscard]] constexpr subrange
312 prev(iter_difference_t<_It> __n = 1) const
313 requires bidirectional_iterator<_It>
321 advance(iter_difference_t<_It> __n)
325 if constexpr (bidirectional_iterator<_It>)
328 ranges::advance(_M_begin, __n);
329 if constexpr (_S_store_size)
330 _M_size._M_size += __detail::__to_unsigned_like(-__n);
334 __glibcxx_assert(__n >= 0);
335 auto __d = __n - ranges::advance(_M_begin, __n, _M_end);
336 if constexpr (_S_store_size)
337 _M_size._M_size -= __detail::__to_unsigned_like(__d);
342 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
343 subrange(_It, _Sent) -> subrange<_It, _Sent>;
345 template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
347 __detail::__make_unsigned_like_t<iter_difference_t<_It>>)
348 -> subrange<_It, _Sent, subrange_kind::sized>;
350 template<borrowed_range _Rng>
352 -> subrange<iterator_t<_Rng>, sentinel_t<_Rng>,
354 || sized_sentinel_for<sentinel_t<_Rng>, iterator_t<_Rng>>)
355 ? subrange_kind::sized : subrange_kind::unsized>;
357 template<borrowed_range _Rng>
359 __detail::__make_unsigned_like_t<range_difference_t<_Rng>>)
360 -> subrange<iterator_t<_Rng>, sentinel_t<_Rng>, subrange_kind::sized>;
362 template<
size_t _Num, class _It, class _Sent, subrange_kind _Kind>
365 get(const subrange<_It, _Sent, _Kind>& __r)
367 if constexpr (_Num == 0)
373 template<
size_t _Num, class _It, class _Sent, subrange_kind _Kind>
376 get(subrange<_It, _Sent, _Kind>&& __r)
378 if constexpr (_Num == 0)
384 template<input_or_output_iterator _It, sentinel_for<_It> _Sent,
386 inline constexpr
bool
387 enable_borrowed_range<subrange<_It, _Sent, _Kind>> = true;
389 template<range _Range>
390 using borrowed_subrange_t =
conditional_t<borrowed_range<_Range>,
391 subrange<iterator_t<_Range>>,
398 template<typename _Iter, typename _Sent, ranges::subrange_kind _Kind>
399 struct tuple_size<ranges::subrange<_Iter, _Sent, _Kind>>
400 : integral_constant<
size_t, 2>
403 template<
typename _Iter,
typename _Sent, ranges::subrange_kind _Kind>
404 struct tuple_element<0, ranges::subrange<_Iter, _Sent, _Kind>>
405 {
using type = _Iter; };
407 template<
typename _Iter,
typename _Sent, ranges::subrange_kind _Kind>
408 struct tuple_element<1, ranges::subrange<_Iter, _Sent, _Kind>>
409 {
using type = _Sent; };
411 template<
typename _Iter,
typename _Sent, ranges::subrange_kind _Kind>
412 struct tuple_element<0, const ranges::subrange<_Iter, _Sent, _Kind>>
413 {
using type = _Iter; };
415 template<
typename _Iter,
typename _Sent, ranges::subrange_kind _Kind>
416 struct tuple_element<1, const ranges::subrange<_Iter, _Sent, _Kind>>
417 {
using type = _Sent; };
419 _GLIBCXX_END_NAMESPACE_VERSION
421 #endif // library concepts
423 #endif // _RANGES_UTIL_H
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
constexpr auto data(_Container &__cont) noexcept(noexcept(__cont.data())) -> decltype(__cont.data())
Return the data pointer of a container.
_Tp * begin(valarray< _Tp > &__va)
Return an iterator pointing to the first element of the valarray.
_Tp * end(valarray< _Tp > &__va)
Return an iterator pointing to one past the last element of the valarray.
typename conditional< _Cond, _Iftrue, _Iffalse >::type conditional_t
Alias template for conditional.
constexpr auto empty(const _Container &__cont) noexcept(noexcept(__cont.empty())) -> decltype(__cont.empty())
Return whether a container is empty.
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.