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 //===----------------------------------------------------------------------===// 9*bdd1243dSDimitry 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> 20*bdd1243dSDimitry Andric #include <__fwd/get.h> 21*bdd1243dSDimitry Andric #include <__fwd/subrange.h> 22349cc55cSDimitry Andric #include <__iterator/advance.h> 23fe6060f1SDimitry Andric #include <__iterator/concepts.h> 24fe6060f1SDimitry Andric #include <__iterator/incrementable_traits.h> 25fe6060f1SDimitry Andric #include <__iterator/iterator_traits.h> 26fe6060f1SDimitry Andric #include <__ranges/access.h> 27fe6060f1SDimitry Andric #include <__ranges/concepts.h> 28fe6060f1SDimitry Andric #include <__ranges/dangling.h> 29fe6060f1SDimitry Andric #include <__ranges/enable_borrowed_range.h> 30fe6060f1SDimitry Andric #include <__ranges/size.h> 31fe6060f1SDimitry Andric #include <__ranges/view_interface.h> 32*bdd1243dSDimitry Andric #include <__tuple_dir/pair_like.h> 33*bdd1243dSDimitry Andric #include <__tuple_dir/tuple_element.h> 34*bdd1243dSDimitry Andric #include <__tuple_dir/tuple_size.h> 35*bdd1243dSDimitry Andric #include <__type_traits/conditional.h> 36*bdd1243dSDimitry Andric #include <__type_traits/decay.h> 37*bdd1243dSDimitry Andric #include <__type_traits/is_pointer.h> 38*bdd1243dSDimitry Andric #include <__type_traits/is_reference.h> 39*bdd1243dSDimitry Andric #include <__type_traits/make_unsigned.h> 40*bdd1243dSDimitry Andric #include <__type_traits/remove_const.h> 41*bdd1243dSDimitry Andric #include <__type_traits/remove_pointer.h> 42349cc55cSDimitry Andric #include <__utility/move.h> 43*bdd1243dSDimitry Andric #include <cstddef> 44fe6060f1SDimitry Andric 45fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 46fe6060f1SDimitry Andric # pragma GCC system_header 47fe6060f1SDimitry Andric #endif 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 50fe6060f1SDimitry Andric 51*bdd1243dSDimitry Andric #if _LIBCPP_STD_VER > 17 52fe6060f1SDimitry Andric 53fe6060f1SDimitry Andric namespace ranges { 54fe6060f1SDimitry Andric template<class _From, class _To> 5504eeddc0SDimitry Andric concept __uses_nonqualification_pointer_conversion = 5604eeddc0SDimitry Andric is_pointer_v<_From> && is_pointer_v<_To> && 5704eeddc0SDimitry Andric !convertible_to<remove_pointer_t<_From>(*)[], remove_pointer_t<_To>(*)[]>; 5804eeddc0SDimitry Andric 5904eeddc0SDimitry Andric template<class _From, class _To> 60fe6060f1SDimitry Andric concept __convertible_to_non_slicing = 61fe6060f1SDimitry Andric convertible_to<_From, _To> && 6204eeddc0SDimitry Andric !__uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>; 63fe6060f1SDimitry Andric 64fe6060f1SDimitry Andric template<class _Pair, class _Iter, class _Sent> 65fe6060f1SDimitry Andric concept __pair_like_convertible_from = 66fe6060f1SDimitry Andric !range<_Pair> && __pair_like<_Pair> && 67fe6060f1SDimitry Andric constructible_from<_Pair, _Iter, _Sent> && 68fe6060f1SDimitry Andric __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && 69fe6060f1SDimitry Andric convertible_to<_Sent, tuple_element_t<1, _Pair>>; 70fe6060f1SDimitry Andric 71fe6060f1SDimitry Andric template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter, 72fe6060f1SDimitry Andric subrange_kind _Kind = sized_sentinel_for<_Sent, _Iter> 73fe6060f1SDimitry Andric ? subrange_kind::sized 74fe6060f1SDimitry Andric : subrange_kind::unsized> 75fe6060f1SDimitry Andric requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>) 76349cc55cSDimitry Andric class _LIBCPP_TEMPLATE_VIS subrange 77349cc55cSDimitry Andric : public view_interface<subrange<_Iter, _Sent, _Kind>> 78349cc55cSDimitry Andric { 7981ad6265SDimitry Andric public: 8081ad6265SDimitry Andric // Note: this is an internal implementation detail that is public only for internal usage. 81349cc55cSDimitry Andric static constexpr bool _StoreSize = (_Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>); 8281ad6265SDimitry Andric 8381ad6265SDimitry Andric private: 84349cc55cSDimitry Andric static constexpr bool _MustProvideSizeAtConstruction = !_StoreSize; // just to improve compiler diagnostics 85349cc55cSDimitry Andric struct _Empty { constexpr _Empty(auto) noexcept { } }; 86349cc55cSDimitry Andric using _Size = conditional_t<_StoreSize, make_unsigned_t<iter_difference_t<_Iter>>, _Empty>; 8781ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Iter __begin_ = _Iter(); 8881ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Sent __end_ = _Sent(); 8981ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _Size __size_ = 0; 90fe6060f1SDimitry Andric 91349cc55cSDimitry Andric public: 92fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 93fe6060f1SDimitry Andric subrange() requires default_initializable<_Iter> = default; 94fe6060f1SDimitry Andric 95fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 96fe6060f1SDimitry Andric constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent) 97349cc55cSDimitry Andric requires _MustProvideSizeAtConstruction 9881ad6265SDimitry Andric : __begin_(std::move(__iter)), __end_(std::move(__sent)) 99349cc55cSDimitry Andric { } 100fe6060f1SDimitry Andric 101fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 102fe6060f1SDimitry Andric constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent, 103fe6060f1SDimitry Andric make_unsigned_t<iter_difference_t<_Iter>> __n) 104fe6060f1SDimitry Andric requires (_Kind == subrange_kind::sized) 10581ad6265SDimitry Andric : __begin_(std::move(__iter)), __end_(std::move(__sent)), __size_(__n) 106349cc55cSDimitry Andric { 107349cc55cSDimitry Andric if constexpr (sized_sentinel_for<_Sent, _Iter>) 108349cc55cSDimitry Andric _LIBCPP_ASSERT((__end_ - __begin_) == static_cast<iter_difference_t<_Iter>>(__n), 109349cc55cSDimitry Andric "std::ranges::subrange was passed an invalid size hint"); 110349cc55cSDimitry Andric } 111fe6060f1SDimitry Andric 112fe6060f1SDimitry Andric template<__different_from<subrange> _Range> 113fe6060f1SDimitry Andric requires borrowed_range<_Range> && 114fe6060f1SDimitry Andric __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && 115fe6060f1SDimitry Andric convertible_to<sentinel_t<_Range>, _Sent> 116fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 117fe6060f1SDimitry Andric constexpr subrange(_Range&& __range) 118349cc55cSDimitry Andric requires (!_StoreSize) 119349cc55cSDimitry Andric : subrange(ranges::begin(__range), ranges::end(__range)) 120349cc55cSDimitry Andric { } 121fe6060f1SDimitry Andric 122fe6060f1SDimitry Andric template<__different_from<subrange> _Range> 123fe6060f1SDimitry Andric requires borrowed_range<_Range> && 124fe6060f1SDimitry Andric __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && 125fe6060f1SDimitry Andric convertible_to<sentinel_t<_Range>, _Sent> 126fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 127fe6060f1SDimitry Andric constexpr subrange(_Range&& __range) 128349cc55cSDimitry Andric requires _StoreSize && sized_range<_Range> 129349cc55cSDimitry Andric : subrange(__range, ranges::size(__range)) 130349cc55cSDimitry Andric { } 131fe6060f1SDimitry Andric 132fe6060f1SDimitry Andric template<borrowed_range _Range> 133fe6060f1SDimitry Andric requires __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && 134fe6060f1SDimitry Andric convertible_to<sentinel_t<_Range>, _Sent> 135fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 136fe6060f1SDimitry Andric constexpr subrange(_Range&& __range, make_unsigned_t<iter_difference_t<_Iter>> __n) 137fe6060f1SDimitry Andric requires (_Kind == subrange_kind::sized) 138349cc55cSDimitry Andric : subrange(ranges::begin(__range), ranges::end(__range), __n) 139349cc55cSDimitry Andric { } 140fe6060f1SDimitry Andric 141fe6060f1SDimitry Andric template<__different_from<subrange> _Pair> 142fe6060f1SDimitry Andric requires __pair_like_convertible_from<_Pair, const _Iter&, const _Sent&> 143fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 144349cc55cSDimitry Andric constexpr operator _Pair() const { 145349cc55cSDimitry Andric return _Pair(__begin_, __end_); 146349cc55cSDimitry Andric } 147fe6060f1SDimitry Andric 148fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 149fe6060f1SDimitry Andric constexpr _Iter begin() const requires copyable<_Iter> { 150349cc55cSDimitry Andric return __begin_; 151fe6060f1SDimitry Andric } 152fe6060f1SDimitry Andric 153fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() requires (!copyable<_Iter>) { 15481ad6265SDimitry Andric return std::move(__begin_); 155fe6060f1SDimitry Andric } 156fe6060f1SDimitry Andric 157fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 158349cc55cSDimitry Andric constexpr _Sent end() const { 159349cc55cSDimitry Andric return __end_; 160349cc55cSDimitry Andric } 161fe6060f1SDimitry Andric 162349cc55cSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { 163349cc55cSDimitry Andric return __begin_ == __end_; 164349cc55cSDimitry Andric } 165fe6060f1SDimitry Andric 166fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 167fe6060f1SDimitry Andric constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const 168fe6060f1SDimitry Andric requires (_Kind == subrange_kind::sized) 169fe6060f1SDimitry Andric { 170349cc55cSDimitry Andric if constexpr (_StoreSize) 171349cc55cSDimitry Andric return __size_; 172fe6060f1SDimitry Andric else 17381ad6265SDimitry Andric return std::__to_unsigned_like(__end_ - __begin_); 174fe6060f1SDimitry Andric } 175fe6060f1SDimitry Andric 176fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) const& 177349cc55cSDimitry Andric requires forward_iterator<_Iter> 178349cc55cSDimitry Andric { 179fe6060f1SDimitry Andric auto __tmp = *this; 180fe6060f1SDimitry Andric __tmp.advance(__n); 181fe6060f1SDimitry Andric return __tmp; 182fe6060f1SDimitry Andric } 183fe6060f1SDimitry Andric 184fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) && { 185fe6060f1SDimitry Andric advance(__n); 18681ad6265SDimitry Andric return std::move(*this); 187fe6060f1SDimitry Andric } 188fe6060f1SDimitry Andric 189fe6060f1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange prev(iter_difference_t<_Iter> __n = 1) const 190349cc55cSDimitry Andric requires bidirectional_iterator<_Iter> 191349cc55cSDimitry Andric { 192fe6060f1SDimitry Andric auto __tmp = *this; 193fe6060f1SDimitry Andric __tmp.advance(-__n); 194fe6060f1SDimitry Andric return __tmp; 195fe6060f1SDimitry Andric } 196fe6060f1SDimitry Andric 197fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 198fe6060f1SDimitry Andric constexpr subrange& advance(iter_difference_t<_Iter> __n) { 199fe6060f1SDimitry Andric if constexpr (bidirectional_iterator<_Iter>) { 200fe6060f1SDimitry Andric if (__n < 0) { 201349cc55cSDimitry Andric ranges::advance(__begin_, __n); 202349cc55cSDimitry Andric if constexpr (_StoreSize) 20381ad6265SDimitry Andric __size_ += std::__to_unsigned_like(-__n); 204fe6060f1SDimitry Andric return *this; 205fe6060f1SDimitry Andric } 206fe6060f1SDimitry Andric } 207fe6060f1SDimitry Andric 208349cc55cSDimitry Andric auto __d = __n - ranges::advance(__begin_, __n, __end_); 209349cc55cSDimitry Andric if constexpr (_StoreSize) 21081ad6265SDimitry Andric __size_ -= std::__to_unsigned_like(__d); 211fe6060f1SDimitry Andric return *this; 212fe6060f1SDimitry Andric } 213fe6060f1SDimitry Andric }; 214fe6060f1SDimitry Andric 215fe6060f1SDimitry Andric template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> 216fe6060f1SDimitry Andric subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>; 217fe6060f1SDimitry Andric 218fe6060f1SDimitry Andric template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> 219fe6060f1SDimitry Andric subrange(_Iter, _Sent, make_unsigned_t<iter_difference_t<_Iter>>) 220fe6060f1SDimitry Andric -> subrange<_Iter, _Sent, subrange_kind::sized>; 221fe6060f1SDimitry Andric 222fe6060f1SDimitry Andric template<borrowed_range _Range> 223fe6060f1SDimitry Andric subrange(_Range&&) -> subrange<iterator_t<_Range>, sentinel_t<_Range>, 224fe6060f1SDimitry Andric (sized_range<_Range> || sized_sentinel_for<sentinel_t<_Range>, iterator_t<_Range>>) 225fe6060f1SDimitry Andric ? subrange_kind::sized : subrange_kind::unsized>; 226fe6060f1SDimitry Andric 227fe6060f1SDimitry Andric template<borrowed_range _Range> 228fe6060f1SDimitry Andric subrange(_Range&&, make_unsigned_t<range_difference_t<_Range>>) 229fe6060f1SDimitry Andric -> subrange<iterator_t<_Range>, sentinel_t<_Range>, subrange_kind::sized>; 230fe6060f1SDimitry Andric 231fe6060f1SDimitry Andric template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> 2321fd87a68SDimitry Andric requires ((_Index == 0 && copyable<_Iter>) || _Index == 1) 233fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 234fe6060f1SDimitry Andric constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) { 235fe6060f1SDimitry Andric if constexpr (_Index == 0) 236fe6060f1SDimitry Andric return __subrange.begin(); 237fe6060f1SDimitry Andric else 238fe6060f1SDimitry Andric return __subrange.end(); 239fe6060f1SDimitry Andric } 240fe6060f1SDimitry Andric 241fe6060f1SDimitry Andric template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> 242fe6060f1SDimitry Andric requires (_Index < 2) 243fe6060f1SDimitry Andric _LIBCPP_HIDE_FROM_ABI 244fe6060f1SDimitry Andric constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) { 245fe6060f1SDimitry Andric if constexpr (_Index == 0) 246fe6060f1SDimitry Andric return __subrange.begin(); 247fe6060f1SDimitry Andric else 248fe6060f1SDimitry Andric return __subrange.end(); 249fe6060f1SDimitry Andric } 250fe6060f1SDimitry Andric 251fe6060f1SDimitry Andric template<class _Ip, class _Sp, subrange_kind _Kp> 252fe6060f1SDimitry Andric inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true; 253fe6060f1SDimitry Andric 254fe6060f1SDimitry Andric template<range _Rp> 255fe6060f1SDimitry Andric using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp>>, dangling>; 256fe6060f1SDimitry Andric } // namespace ranges 257fe6060f1SDimitry Andric 258349cc55cSDimitry Andric // [range.subrange.general] 259349cc55cSDimitry Andric 260fe6060f1SDimitry Andric using ranges::get; 261fe6060f1SDimitry Andric 262349cc55cSDimitry Andric // [ranges.syn] 263349cc55cSDimitry Andric 264349cc55cSDimitry Andric template<class _Ip, class _Sp, ranges::subrange_kind _Kp> 265349cc55cSDimitry Andric struct tuple_size<ranges::subrange<_Ip, _Sp, _Kp>> : integral_constant<size_t, 2> {}; 266349cc55cSDimitry Andric 267349cc55cSDimitry Andric template<class _Ip, class _Sp, ranges::subrange_kind _Kp> 268349cc55cSDimitry Andric struct tuple_element<0, ranges::subrange<_Ip, _Sp, _Kp>> { 269349cc55cSDimitry Andric using type = _Ip; 270349cc55cSDimitry Andric }; 271349cc55cSDimitry Andric 272349cc55cSDimitry Andric template<class _Ip, class _Sp, ranges::subrange_kind _Kp> 273349cc55cSDimitry Andric struct tuple_element<1, ranges::subrange<_Ip, _Sp, _Kp>> { 274349cc55cSDimitry Andric using type = _Sp; 275349cc55cSDimitry Andric }; 276349cc55cSDimitry Andric 277349cc55cSDimitry Andric template<class _Ip, class _Sp, ranges::subrange_kind _Kp> 278349cc55cSDimitry Andric struct tuple_element<0, const ranges::subrange<_Ip, _Sp, _Kp>> { 279349cc55cSDimitry Andric using type = _Ip; 280349cc55cSDimitry Andric }; 281349cc55cSDimitry Andric 282349cc55cSDimitry Andric template<class _Ip, class _Sp, ranges::subrange_kind _Kp> 283349cc55cSDimitry Andric struct tuple_element<1, const ranges::subrange<_Ip, _Sp, _Kp>> { 284349cc55cSDimitry Andric using type = _Sp; 285349cc55cSDimitry Andric }; 286fe6060f1SDimitry Andric 287*bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER > 17 288fe6060f1SDimitry Andric 289fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD 290fe6060f1SDimitry Andric 291fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_SUBRANGE_H 292