1fe6060f1SDimitry Andric // -*- C++ -*- 2fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 3fe6060f1SDimitry Andric // 4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7fe6060f1SDimitry Andric // 8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 9bdd1243dSDimitry Andric 10fe6060f1SDimitry Andric #ifndef _LIBCPP___RANGES_SUBRANGE_H 11fe6060f1SDimitry Andric #define _LIBCPP___RANGES_SUBRANGE_H 12fe6060f1SDimitry Andric 1381ad6265SDimitry Andric #include <__assert> 14349cc55cSDimitry Andric #include <__concepts/constructible.h> 15349cc55cSDimitry Andric #include <__concepts/convertible_to.h> 16349cc55cSDimitry Andric #include <__concepts/copyable.h> 17349cc55cSDimitry Andric #include <__concepts/derived_from.h> 18349cc55cSDimitry Andric #include <__concepts/different_from.h> 19fe6060f1SDimitry Andric #include <__config> 20bdd1243dSDimitry Andric #include <__fwd/subrange.h> 21349cc55cSDimitry Andric #include <__iterator/advance.h> 22fe6060f1SDimitry Andric #include <__iterator/concepts.h> 23fe6060f1SDimitry Andric #include <__iterator/incrementable_traits.h> 24fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h> 25fe6060f1SDimitry Andric #include <__ranges/access.h> 26fe6060f1SDimitry Andric #include <__ranges/concepts.h> 27fe6060f1SDimitry Andric #include <__ranges/dangling.h> 28fe6060f1SDimitry Andric #include <__ranges/enable_borrowed_range.h> 29fe6060f1SDimitry Andric #include <__ranges/size.h> 30fe6060f1SDimitry Andric #include <__ranges/view_interface.h> 3106c3fb27SDimitry Andric #include <__tuple/tuple_element.h> 32*0fca6ea1SDimitry Andric #include <__tuple/tuple_like_no_subrange.h> 3306c3fb27SDimitry Andric #include <__tuple/tuple_size.h> 34bdd1243dSDimitry Andric #include <__type_traits/conditional.h> 35bdd1243dSDimitry Andric #include <__type_traits/decay.h> 36bdd1243dSDimitry Andric #include <__type_traits/is_pointer.h> 37bdd1243dSDimitry Andric #include <__type_traits/is_reference.h> 38bdd1243dSDimitry Andric #include <__type_traits/make_unsigned.h> 39bdd1243dSDimitry Andric #include <__type_traits/remove_const.h> 40bdd1243dSDimitry Andric #include <__type_traits/remove_pointer.h> 41349cc55cSDimitry Andric #include <__utility/move.h> 42bdd1243dSDimitry Andric #include <cstddef> 43fe6060f1SDimitry Andric 44fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 45fe6060f1SDimitry Andric # pragma GCC system_header 46fe6060f1SDimitry Andric #endif 47fe6060f1SDimitry Andric 4806c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS 4906c3fb27SDimitry Andric #include <__undef_macros> 5006c3fb27SDimitry Andric 51fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 52fe6060f1SDimitry Andric 5306c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20 54fe6060f1SDimitry Andric 55fe6060f1SDimitry Andric namespace ranges { 56fe6060f1SDimitry Andric template <class _From, class _To> 5704eeddc0SDimitry Andric concept __uses_nonqualification_pointer_conversion = 5804eeddc0SDimitry Andric is_pointer_v<_From> && is_pointer_v<_To> && 5904eeddc0SDimitry Andric !convertible_to<remove_pointer_t<_From> (*)[], remove_pointer_t<_To> (*)[]>; 6004eeddc0SDimitry Andric 6104eeddc0SDimitry Andric template <class _From, class _To> 62fe6060f1SDimitry Andric concept __convertible_to_non_slicing = 63cb14a3feSDimitry Andric convertible_to<_From, _To> && !__uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>; 64fe6060f1SDimitry Andric 65fe6060f1SDimitry Andric template <class _Pair, class _Iter, class _Sent> 66fe6060f1SDimitry Andric concept __pair_like_convertible_from = 67*0fca6ea1SDimitry Andric !range<_Pair> && __pair_like_no_subrange<_Pair> && constructible_from<_Pair, _Iter, _Sent> && 68cb14a3feSDimitry Andric __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && convertible_to<_Sent, tuple_element_t<1, _Pair>>; 69fe6060f1SDimitry Andric 70cb14a3feSDimitry Andric template <input_or_output_iterator _Iter, 71cb14a3feSDimitry Andric sentinel_for<_Iter> _Sent = _Iter, 72cb14a3feSDimitry Andric subrange_kind _Kind = sized_sentinel_for<_Sent, _Iter> ? subrange_kind::sized : subrange_kind::unsized> 73fe6060f1SDimitry Andric requires(_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>) 74cb14a3feSDimitry Andric class _LIBCPP_TEMPLATE_VIS subrange : public view_interface<subrange<_Iter, _Sent, _Kind>> { 7581ad6265SDimitry Andric public: 7681ad6265SDimitry Andric // Note: this is an internal implementation detail that is public only for internal usage. 77349cc55cSDimitry Andric static constexpr bool _StoreSize = (_Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>); 7881ad6265SDimitry Andric 7981ad6265SDimitry Andric private: 80349cc55cSDimitry Andric static constexpr bool _MustProvideSizeAtConstruction = !_StoreSize; // just to improve compiler diagnostics 81cb14a3feSDimitry Andric struct _Empty { 82cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Empty(auto) noexcept {} 83cb14a3feSDimitry Andric }; 84349cc55cSDimitry Andric using _Size = conditional_t<_StoreSize, make_unsigned_t<iter_difference_t<_Iter>>, _Empty>; 8581ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Iter __begin_ = _Iter(); 8681ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Sent __end_ = _Sent(); 8781ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Size __size_ = 0; 88fe6060f1SDimitry Andric 89349cc55cSDimitry Andric public: 90cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI subrange() 91cb14a3feSDimitry Andric requires default_initializable<_Iter> 92cb14a3feSDimitry Andric = default; 93fe6060f1SDimitry Andric 94cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent) 95349cc55cSDimitry Andric requires _MustProvideSizeAtConstruction 96cb14a3feSDimitry Andric : __begin_(std::move(__iter)), __end_(std::move(__sent)) {} 97fe6060f1SDimitry Andric 98cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr subrange( 99cb14a3feSDimitry Andric __convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent, make_unsigned_t<iter_difference_t<_Iter>> __n) 100fe6060f1SDimitry Andric requires(_Kind == subrange_kind::sized) 101cb14a3feSDimitry Andric : __begin_(std::move(__iter)), __end_(std::move(__sent)), __size_(__n) { 102349cc55cSDimitry Andric if constexpr (sized_sentinel_for<_Sent, _Iter>) 103cb14a3feSDimitry Andric _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS((__end_ - __begin_) == static_cast<iter_difference_t<_Iter>>(__n), 104349cc55cSDimitry Andric "std::ranges::subrange was passed an invalid size hint"); 105349cc55cSDimitry Andric } 106fe6060f1SDimitry Andric 107fe6060f1SDimitry Andric template <__different_from<subrange> _Range> 108cb14a3feSDimitry Andric requires borrowed_range<_Range> && __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && 109fe6060f1SDimitry Andric convertible_to<sentinel_t<_Range>, _Sent> 110cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range) 111349cc55cSDimitry Andric requires(!_StoreSize) 112cb14a3feSDimitry Andric : subrange(ranges::begin(__range), ranges::end(__range)) {} 113fe6060f1SDimitry Andric 114fe6060f1SDimitry Andric template <__different_from<subrange> _Range> 115cb14a3feSDimitry Andric requires borrowed_range<_Range> && __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && 116fe6060f1SDimitry Andric convertible_to<sentinel_t<_Range>, _Sent> 117cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range) 118349cc55cSDimitry Andric requires _StoreSize && sized_range<_Range> 119cb14a3feSDimitry Andric : subrange(__range, ranges::size(__range)) {} 120fe6060f1SDimitry Andric 121fe6060f1SDimitry Andric template <borrowed_range _Range> 122fe6060f1SDimitry Andric requires __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && 123fe6060f1SDimitry Andric convertible_to<sentinel_t<_Range>, _Sent> 124cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range, make_unsigned_t<iter_difference_t<_Iter>> __n) 125fe6060f1SDimitry Andric requires(_Kind == subrange_kind::sized) 126cb14a3feSDimitry Andric : subrange(ranges::begin(__range), ranges::end(__range), __n) {} 127fe6060f1SDimitry Andric 128*0fca6ea1SDimitry Andric template <__pair_like_convertible_from<const _Iter&, const _Sent&> _Pair> 129cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr operator _Pair() const { 130349cc55cSDimitry Andric return _Pair(__begin_, __end_); 131349cc55cSDimitry Andric } 132fe6060f1SDimitry Andric 133cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() const 134cb14a3feSDimitry Andric requires copyable<_Iter> 135cb14a3feSDimitry Andric { 136349cc55cSDimitry Andric return __begin_; 137fe6060f1SDimitry Andric } 138fe6060f1SDimitry Andric 139cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() 140cb14a3feSDimitry Andric requires(!copyable<_Iter>) 141cb14a3feSDimitry Andric { 14281ad6265SDimitry Andric return std::move(__begin_); 143fe6060f1SDimitry Andric } 144fe6060f1SDimitry Andric 145cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Sent end() const { return __end_; } 146fe6060f1SDimitry Andric 147cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return __begin_ == __end_; } 148fe6060f1SDimitry Andric 149cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const 150fe6060f1SDimitry Andric requires(_Kind == subrange_kind::sized) 151fe6060f1SDimitry Andric { 152349cc55cSDimitry Andric if constexpr (_StoreSize) 153349cc55cSDimitry Andric return __size_; 154fe6060f1SDimitry Andric else 15581ad6265SDimitry Andric return std::__to_unsigned_like(__end_ - __begin_); 156fe6060f1SDimitry Andric } 157fe6060f1SDimitry Andric 158fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) const& 159349cc55cSDimitry Andric requires forward_iterator<_Iter> 160349cc55cSDimitry Andric { 161fe6060f1SDimitry Andric auto __tmp = *this; 162fe6060f1SDimitry Andric __tmp.advance(__n); 163fe6060f1SDimitry Andric return __tmp; 164fe6060f1SDimitry Andric } 165fe6060f1SDimitry Andric 166fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) && { 167fe6060f1SDimitry Andric advance(__n); 16881ad6265SDimitry Andric return std::move(*this); 169fe6060f1SDimitry Andric } 170fe6060f1SDimitry Andric 171fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange prev(iter_difference_t<_Iter> __n = 1) const 172349cc55cSDimitry Andric requires bidirectional_iterator<_Iter> 173349cc55cSDimitry Andric { 174fe6060f1SDimitry Andric auto __tmp = *this; 175fe6060f1SDimitry Andric __tmp.advance(-__n); 176fe6060f1SDimitry Andric return __tmp; 177fe6060f1SDimitry Andric } 178fe6060f1SDimitry Andric 179cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr subrange& advance(iter_difference_t<_Iter> __n) { 180fe6060f1SDimitry Andric if constexpr (bidirectional_iterator<_Iter>) { 181fe6060f1SDimitry Andric if (__n < 0) { 182349cc55cSDimitry Andric ranges::advance(__begin_, __n); 183349cc55cSDimitry Andric if constexpr (_StoreSize) 18481ad6265SDimitry Andric __size_ += std::__to_unsigned_like(-__n); 185fe6060f1SDimitry Andric return *this; 186fe6060f1SDimitry Andric } 187fe6060f1SDimitry Andric } 188fe6060f1SDimitry Andric 189349cc55cSDimitry Andric auto __d = __n - ranges::advance(__begin_, __n, __end_); 190349cc55cSDimitry Andric if constexpr (_StoreSize) 19181ad6265SDimitry Andric __size_ -= std::__to_unsigned_like(__d); 192fe6060f1SDimitry Andric return *this; 193fe6060f1SDimitry Andric } 194fe6060f1SDimitry Andric }; 195fe6060f1SDimitry Andric 196fe6060f1SDimitry Andric template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> 197fe6060f1SDimitry Andric subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>; 198fe6060f1SDimitry Andric 199fe6060f1SDimitry Andric template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> 200cb14a3feSDimitry Andric subrange(_Iter, _Sent, make_unsigned_t<iter_difference_t<_Iter>>) -> subrange<_Iter, _Sent, subrange_kind::sized>; 201fe6060f1SDimitry Andric 202fe6060f1SDimitry Andric template <borrowed_range _Range> 203*0fca6ea1SDimitry Andric subrange(_Range&&) -> subrange<iterator_t<_Range>, 204cb14a3feSDimitry Andric sentinel_t<_Range>, 205fe6060f1SDimitry Andric (sized_range<_Range> || sized_sentinel_for<sentinel_t<_Range>, iterator_t<_Range>>) 206cb14a3feSDimitry Andric ? subrange_kind::sized 207cb14a3feSDimitry Andric : subrange_kind::unsized>; 208fe6060f1SDimitry Andric 209fe6060f1SDimitry Andric template <borrowed_range _Range> 210fe6060f1SDimitry Andric subrange(_Range&&, make_unsigned_t<range_difference_t<_Range>>) 211fe6060f1SDimitry Andric -> subrange<iterator_t<_Range>, sentinel_t<_Range>, subrange_kind::sized>; 212fe6060f1SDimitry Andric 213fe6060f1SDimitry Andric template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> 2141fd87a68SDimitry Andric requires((_Index == 0 && copyable<_Iter>) || _Index == 1) 215cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) { 216fe6060f1SDimitry Andric if constexpr (_Index == 0) 217fe6060f1SDimitry Andric return __subrange.begin(); 218fe6060f1SDimitry Andric else 219fe6060f1SDimitry Andric return __subrange.end(); 220fe6060f1SDimitry Andric } 221fe6060f1SDimitry Andric 222fe6060f1SDimitry Andric template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> 223fe6060f1SDimitry Andric requires(_Index < 2) 224cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) { 225fe6060f1SDimitry Andric if constexpr (_Index == 0) 226fe6060f1SDimitry Andric return __subrange.begin(); 227fe6060f1SDimitry Andric else 228fe6060f1SDimitry Andric return __subrange.end(); 229fe6060f1SDimitry Andric } 230fe6060f1SDimitry Andric 231fe6060f1SDimitry Andric template <class _Ip, class _Sp, subrange_kind _Kp> 232fe6060f1SDimitry Andric inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true; 233fe6060f1SDimitry Andric 234fe6060f1SDimitry Andric template <range _Rp> 235fe6060f1SDimitry Andric using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp>>, dangling>; 236fe6060f1SDimitry Andric } // namespace ranges 237fe6060f1SDimitry Andric 238349cc55cSDimitry Andric // [range.subrange.general] 239349cc55cSDimitry Andric 240fe6060f1SDimitry Andric using ranges::get; 241fe6060f1SDimitry Andric 242349cc55cSDimitry Andric // [ranges.syn] 243349cc55cSDimitry Andric 244349cc55cSDimitry Andric template <class _Ip, class _Sp, ranges::subrange_kind _Kp> 245349cc55cSDimitry Andric struct tuple_size<ranges::subrange<_Ip, _Sp, _Kp>> : integral_constant<size_t, 2> {}; 246349cc55cSDimitry Andric 247349cc55cSDimitry Andric template <class _Ip, class _Sp, ranges::subrange_kind _Kp> 248349cc55cSDimitry Andric struct tuple_element<0, ranges::subrange<_Ip, _Sp, _Kp>> { 249349cc55cSDimitry Andric using type = _Ip; 250349cc55cSDimitry Andric }; 251349cc55cSDimitry Andric 252349cc55cSDimitry Andric template <class _Ip, class _Sp, ranges::subrange_kind _Kp> 253349cc55cSDimitry Andric struct tuple_element<1, ranges::subrange<_Ip, _Sp, _Kp>> { 254349cc55cSDimitry Andric using type = _Sp; 255349cc55cSDimitry Andric }; 256349cc55cSDimitry Andric 257349cc55cSDimitry Andric template <class _Ip, class _Sp, ranges::subrange_kind _Kp> 258349cc55cSDimitry Andric struct tuple_element<0, const ranges::subrange<_Ip, _Sp, _Kp>> { 259349cc55cSDimitry Andric using type = _Ip; 260349cc55cSDimitry Andric }; 261349cc55cSDimitry Andric 262349cc55cSDimitry Andric template <class _Ip, class _Sp, ranges::subrange_kind _Kp> 263349cc55cSDimitry Andric struct tuple_element<1, const ranges::subrange<_Ip, _Sp, _Kp>> { 264349cc55cSDimitry Andric using type = _Sp; 265349cc55cSDimitry Andric }; 266fe6060f1SDimitry Andric 26706c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20 268fe6060f1SDimitry Andric 269fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 270fe6060f1SDimitry Andric 27106c3fb27SDimitry Andric _LIBCPP_POP_MACROS 27206c3fb27SDimitry Andric 273fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_SUBRANGE_H 274