1e78f53d1SNikolas Klauser // -*- C++ -*- 2e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 3e78f53d1SNikolas Klauser // 4e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 6e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7e78f53d1SNikolas Klauser // 8e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===// 9e78f53d1SNikolas Klauser 10*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___RANGES_SUBRANGE_H 11*ce777190SNikolas Klauser #define _LIBCPP___CXX03___RANGES_SUBRANGE_H 12e78f53d1SNikolas Klauser 1373fbae83SNikolas Klauser #include <__cxx03/__assert> 1473fbae83SNikolas Klauser #include <__cxx03/__concepts/constructible.h> 1573fbae83SNikolas Klauser #include <__cxx03/__concepts/convertible_to.h> 1673fbae83SNikolas Klauser #include <__cxx03/__concepts/copyable.h> 1773fbae83SNikolas Klauser #include <__cxx03/__concepts/derived_from.h> 1873fbae83SNikolas Klauser #include <__cxx03/__concepts/different_from.h> 1973fbae83SNikolas Klauser #include <__cxx03/__config> 2073fbae83SNikolas Klauser #include <__cxx03/__fwd/subrange.h> 2173fbae83SNikolas Klauser #include <__cxx03/__iterator/advance.h> 2273fbae83SNikolas Klauser #include <__cxx03/__iterator/concepts.h> 2373fbae83SNikolas Klauser #include <__cxx03/__iterator/incrementable_traits.h> 2473fbae83SNikolas Klauser #include <__cxx03/__iterator/iterator_traits.h> 2573fbae83SNikolas Klauser #include <__cxx03/__ranges/access.h> 2673fbae83SNikolas Klauser #include <__cxx03/__ranges/concepts.h> 2773fbae83SNikolas Klauser #include <__cxx03/__ranges/dangling.h> 2873fbae83SNikolas Klauser #include <__cxx03/__ranges/enable_borrowed_range.h> 2973fbae83SNikolas Klauser #include <__cxx03/__ranges/size.h> 3073fbae83SNikolas Klauser #include <__cxx03/__ranges/view_interface.h> 3173fbae83SNikolas Klauser #include <__cxx03/__tuple/tuple_element.h> 3273fbae83SNikolas Klauser #include <__cxx03/__tuple/tuple_like_no_subrange.h> 3373fbae83SNikolas Klauser #include <__cxx03/__tuple/tuple_size.h> 3473fbae83SNikolas Klauser #include <__cxx03/__type_traits/conditional.h> 3573fbae83SNikolas Klauser #include <__cxx03/__type_traits/decay.h> 3673fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_pointer.h> 3773fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_reference.h> 3873fbae83SNikolas Klauser #include <__cxx03/__type_traits/make_unsigned.h> 3973fbae83SNikolas Klauser #include <__cxx03/__type_traits/remove_const.h> 4073fbae83SNikolas Klauser #include <__cxx03/__type_traits/remove_pointer.h> 4173fbae83SNikolas Klauser #include <__cxx03/__utility/move.h> 4273fbae83SNikolas Klauser #include <__cxx03/cstddef> 43e78f53d1SNikolas Klauser 44e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 45e78f53d1SNikolas Klauser # pragma GCC system_header 46e78f53d1SNikolas Klauser #endif 47e78f53d1SNikolas Klauser 48e78f53d1SNikolas Klauser _LIBCPP_PUSH_MACROS 4973fbae83SNikolas Klauser #include <__cxx03/__undef_macros> 50e78f53d1SNikolas Klauser 51e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 52e78f53d1SNikolas Klauser 53e78f53d1SNikolas Klauser #if _LIBCPP_STD_VER >= 20 54e78f53d1SNikolas Klauser 55e78f53d1SNikolas Klauser namespace ranges { 56e78f53d1SNikolas Klauser template <class _From, class _To> 57e78f53d1SNikolas Klauser concept __uses_nonqualification_pointer_conversion = 58e78f53d1SNikolas Klauser is_pointer_v<_From> && is_pointer_v<_To> && 59e78f53d1SNikolas Klauser !convertible_to<remove_pointer_t<_From> (*)[], remove_pointer_t<_To> (*)[]>; 60e78f53d1SNikolas Klauser 61e78f53d1SNikolas Klauser template <class _From, class _To> 62e78f53d1SNikolas Klauser concept __convertible_to_non_slicing = 63e78f53d1SNikolas Klauser convertible_to<_From, _To> && !__uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>; 64e78f53d1SNikolas Klauser 65e78f53d1SNikolas Klauser template <class _Pair, class _Iter, class _Sent> 66e78f53d1SNikolas Klauser concept __pair_like_convertible_from = 67e78f53d1SNikolas Klauser !range<_Pair> && __pair_like_no_subrange<_Pair> && constructible_from<_Pair, _Iter, _Sent> && 68e78f53d1SNikolas Klauser __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && convertible_to<_Sent, tuple_element_t<1, _Pair>>; 69e78f53d1SNikolas Klauser 70e78f53d1SNikolas Klauser template <input_or_output_iterator _Iter, 71e78f53d1SNikolas Klauser sentinel_for<_Iter> _Sent = _Iter, 72e78f53d1SNikolas Klauser subrange_kind _Kind = sized_sentinel_for<_Sent, _Iter> ? subrange_kind::sized : subrange_kind::unsized> 73e78f53d1SNikolas Klauser requires(_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>) 74e78f53d1SNikolas Klauser class _LIBCPP_TEMPLATE_VIS subrange : public view_interface<subrange<_Iter, _Sent, _Kind>> { 75e78f53d1SNikolas Klauser public: 76e78f53d1SNikolas Klauser // Note: this is an internal implementation detail that is public only for internal usage. 77e78f53d1SNikolas Klauser static constexpr bool _StoreSize = (_Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>); 78e78f53d1SNikolas Klauser 79e78f53d1SNikolas Klauser private: 80e78f53d1SNikolas Klauser static constexpr bool _MustProvideSizeAtConstruction = !_StoreSize; // just to improve compiler diagnostics 81e78f53d1SNikolas Klauser struct _Empty { 82e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr _Empty(auto) noexcept {} 83e78f53d1SNikolas Klauser }; 84e78f53d1SNikolas Klauser using _Size = conditional_t<_StoreSize, make_unsigned_t<iter_difference_t<_Iter>>, _Empty>; 85e78f53d1SNikolas Klauser _LIBCPP_NO_UNIQUE_ADDRESS _Iter __begin_ = _Iter(); 86e78f53d1SNikolas Klauser _LIBCPP_NO_UNIQUE_ADDRESS _Sent __end_ = _Sent(); 87e78f53d1SNikolas Klauser _LIBCPP_NO_UNIQUE_ADDRESS _Size __size_ = 0; 88e78f53d1SNikolas Klauser 89e78f53d1SNikolas Klauser public: 90e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI subrange() 91e78f53d1SNikolas Klauser requires default_initializable<_Iter> 92e78f53d1SNikolas Klauser = default; 93e78f53d1SNikolas Klauser 94e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent) 95e78f53d1SNikolas Klauser requires _MustProvideSizeAtConstruction 96e78f53d1SNikolas Klauser : __begin_(std::move(__iter)), __end_(std::move(__sent)) {} 97e78f53d1SNikolas Klauser 98e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr subrange( 99e78f53d1SNikolas Klauser __convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent, make_unsigned_t<iter_difference_t<_Iter>> __n) 100e78f53d1SNikolas Klauser requires(_Kind == subrange_kind::sized) 101e78f53d1SNikolas Klauser : __begin_(std::move(__iter)), __end_(std::move(__sent)), __size_(__n) { 102e78f53d1SNikolas Klauser if constexpr (sized_sentinel_for<_Sent, _Iter>) 103e78f53d1SNikolas Klauser _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS((__end_ - __begin_) == static_cast<iter_difference_t<_Iter>>(__n), 104e78f53d1SNikolas Klauser "std::ranges::subrange was passed an invalid size hint"); 105e78f53d1SNikolas Klauser } 106e78f53d1SNikolas Klauser 107e78f53d1SNikolas Klauser template <__different_from<subrange> _Range> 108e78f53d1SNikolas Klauser requires borrowed_range<_Range> && __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && 109e78f53d1SNikolas Klauser convertible_to<sentinel_t<_Range>, _Sent> 110e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range) 111e78f53d1SNikolas Klauser requires(!_StoreSize) 112e78f53d1SNikolas Klauser : subrange(ranges::begin(__range), ranges::end(__range)) {} 113e78f53d1SNikolas Klauser 114e78f53d1SNikolas Klauser template <__different_from<subrange> _Range> 115e78f53d1SNikolas Klauser requires borrowed_range<_Range> && __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && 116e78f53d1SNikolas Klauser convertible_to<sentinel_t<_Range>, _Sent> 117e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range) 118e78f53d1SNikolas Klauser requires _StoreSize && sized_range<_Range> 119e78f53d1SNikolas Klauser : subrange(__range, ranges::size(__range)) {} 120e78f53d1SNikolas Klauser 121e78f53d1SNikolas Klauser template <borrowed_range _Range> 122e78f53d1SNikolas Klauser requires __convertible_to_non_slicing<iterator_t<_Range>, _Iter> && 123e78f53d1SNikolas Klauser convertible_to<sentinel_t<_Range>, _Sent> 124e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range, make_unsigned_t<iter_difference_t<_Iter>> __n) 125e78f53d1SNikolas Klauser requires(_Kind == subrange_kind::sized) 126e78f53d1SNikolas Klauser : subrange(ranges::begin(__range), ranges::end(__range), __n) {} 127e78f53d1SNikolas Klauser 128e78f53d1SNikolas Klauser template <__pair_like_convertible_from<const _Iter&, const _Sent&> _Pair> 129e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr operator _Pair() const { 130e78f53d1SNikolas Klauser return _Pair(__begin_, __end_); 131e78f53d1SNikolas Klauser } 132e78f53d1SNikolas Klauser 133e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() const 134e78f53d1SNikolas Klauser requires copyable<_Iter> 135e78f53d1SNikolas Klauser { 136e78f53d1SNikolas Klauser return __begin_; 137e78f53d1SNikolas Klauser } 138e78f53d1SNikolas Klauser 139e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() 140e78f53d1SNikolas Klauser requires(!copyable<_Iter>) 141e78f53d1SNikolas Klauser { 142e78f53d1SNikolas Klauser return std::move(__begin_); 143e78f53d1SNikolas Klauser } 144e78f53d1SNikolas Klauser 145e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr _Sent end() const { return __end_; } 146e78f53d1SNikolas Klauser 147e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return __begin_ == __end_; } 148e78f53d1SNikolas Klauser 149e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const 150e78f53d1SNikolas Klauser requires(_Kind == subrange_kind::sized) 151e78f53d1SNikolas Klauser { 152e78f53d1SNikolas Klauser if constexpr (_StoreSize) 153e78f53d1SNikolas Klauser return __size_; 154e78f53d1SNikolas Klauser else 155e78f53d1SNikolas Klauser return std::__to_unsigned_like(__end_ - __begin_); 156e78f53d1SNikolas Klauser } 157e78f53d1SNikolas Klauser 158e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) const& 159e78f53d1SNikolas Klauser requires forward_iterator<_Iter> 160e78f53d1SNikolas Klauser { 161e78f53d1SNikolas Klauser auto __tmp = *this; 162e78f53d1SNikolas Klauser __tmp.advance(__n); 163e78f53d1SNikolas Klauser return __tmp; 164e78f53d1SNikolas Klauser } 165e78f53d1SNikolas Klauser 166e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) && { 167e78f53d1SNikolas Klauser advance(__n); 168e78f53d1SNikolas Klauser return std::move(*this); 169e78f53d1SNikolas Klauser } 170e78f53d1SNikolas Klauser 171e78f53d1SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange prev(iter_difference_t<_Iter> __n = 1) const 172e78f53d1SNikolas Klauser requires bidirectional_iterator<_Iter> 173e78f53d1SNikolas Klauser { 174e78f53d1SNikolas Klauser auto __tmp = *this; 175e78f53d1SNikolas Klauser __tmp.advance(-__n); 176e78f53d1SNikolas Klauser return __tmp; 177e78f53d1SNikolas Klauser } 178e78f53d1SNikolas Klauser 179e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr subrange& advance(iter_difference_t<_Iter> __n) { 180e78f53d1SNikolas Klauser if constexpr (bidirectional_iterator<_Iter>) { 181e78f53d1SNikolas Klauser if (__n < 0) { 182e78f53d1SNikolas Klauser ranges::advance(__begin_, __n); 183e78f53d1SNikolas Klauser if constexpr (_StoreSize) 184e78f53d1SNikolas Klauser __size_ += std::__to_unsigned_like(-__n); 185e78f53d1SNikolas Klauser return *this; 186e78f53d1SNikolas Klauser } 187e78f53d1SNikolas Klauser } 188e78f53d1SNikolas Klauser 189e78f53d1SNikolas Klauser auto __d = __n - ranges::advance(__begin_, __n, __end_); 190e78f53d1SNikolas Klauser if constexpr (_StoreSize) 191e78f53d1SNikolas Klauser __size_ -= std::__to_unsigned_like(__d); 192e78f53d1SNikolas Klauser return *this; 193e78f53d1SNikolas Klauser } 194e78f53d1SNikolas Klauser }; 195e78f53d1SNikolas Klauser 196e78f53d1SNikolas Klauser template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> 197e78f53d1SNikolas Klauser subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>; 198e78f53d1SNikolas Klauser 199e78f53d1SNikolas Klauser template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent> 200e78f53d1SNikolas Klauser subrange(_Iter, _Sent, make_unsigned_t<iter_difference_t<_Iter>>) -> subrange<_Iter, _Sent, subrange_kind::sized>; 201e78f53d1SNikolas Klauser 202e78f53d1SNikolas Klauser template <borrowed_range _Range> 203e78f53d1SNikolas Klauser subrange(_Range&&) -> subrange<iterator_t<_Range>, 204e78f53d1SNikolas Klauser sentinel_t<_Range>, 205e78f53d1SNikolas Klauser (sized_range<_Range> || sized_sentinel_for<sentinel_t<_Range>, iterator_t<_Range>>) 206e78f53d1SNikolas Klauser ? subrange_kind::sized 207e78f53d1SNikolas Klauser : subrange_kind::unsized>; 208e78f53d1SNikolas Klauser 209e78f53d1SNikolas Klauser template <borrowed_range _Range> 210e78f53d1SNikolas Klauser subrange(_Range&&, make_unsigned_t<range_difference_t<_Range>>) 211e78f53d1SNikolas Klauser -> subrange<iterator_t<_Range>, sentinel_t<_Range>, subrange_kind::sized>; 212e78f53d1SNikolas Klauser 213e78f53d1SNikolas Klauser template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> 214e78f53d1SNikolas Klauser requires((_Index == 0 && copyable<_Iter>) || _Index == 1) 215e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) { 216e78f53d1SNikolas Klauser if constexpr (_Index == 0) 217e78f53d1SNikolas Klauser return __subrange.begin(); 218e78f53d1SNikolas Klauser else 219e78f53d1SNikolas Klauser return __subrange.end(); 220e78f53d1SNikolas Klauser } 221e78f53d1SNikolas Klauser 222e78f53d1SNikolas Klauser template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind> 223e78f53d1SNikolas Klauser requires(_Index < 2) 224e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) { 225e78f53d1SNikolas Klauser if constexpr (_Index == 0) 226e78f53d1SNikolas Klauser return __subrange.begin(); 227e78f53d1SNikolas Klauser else 228e78f53d1SNikolas Klauser return __subrange.end(); 229e78f53d1SNikolas Klauser } 230e78f53d1SNikolas Klauser 231e78f53d1SNikolas Klauser template <class _Ip, class _Sp, subrange_kind _Kp> 232e78f53d1SNikolas Klauser inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true; 233e78f53d1SNikolas Klauser 234e78f53d1SNikolas Klauser template <range _Rp> 235e78f53d1SNikolas Klauser using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp>>, dangling>; 236e78f53d1SNikolas Klauser } // namespace ranges 237e78f53d1SNikolas Klauser 238e78f53d1SNikolas Klauser // [range.subrange.general] 239e78f53d1SNikolas Klauser 240e78f53d1SNikolas Klauser using ranges::get; 241e78f53d1SNikolas Klauser 242e78f53d1SNikolas Klauser // [ranges.syn] 243e78f53d1SNikolas Klauser 244e78f53d1SNikolas Klauser template <class _Ip, class _Sp, ranges::subrange_kind _Kp> 245e78f53d1SNikolas Klauser struct tuple_size<ranges::subrange<_Ip, _Sp, _Kp>> : integral_constant<size_t, 2> {}; 246e78f53d1SNikolas Klauser 247e78f53d1SNikolas Klauser template <class _Ip, class _Sp, ranges::subrange_kind _Kp> 248e78f53d1SNikolas Klauser struct tuple_element<0, ranges::subrange<_Ip, _Sp, _Kp>> { 249e78f53d1SNikolas Klauser using type = _Ip; 250e78f53d1SNikolas Klauser }; 251e78f53d1SNikolas Klauser 252e78f53d1SNikolas Klauser template <class _Ip, class _Sp, ranges::subrange_kind _Kp> 253e78f53d1SNikolas Klauser struct tuple_element<1, ranges::subrange<_Ip, _Sp, _Kp>> { 254e78f53d1SNikolas Klauser using type = _Sp; 255e78f53d1SNikolas Klauser }; 256e78f53d1SNikolas Klauser 257e78f53d1SNikolas Klauser template <class _Ip, class _Sp, ranges::subrange_kind _Kp> 258e78f53d1SNikolas Klauser struct tuple_element<0, const ranges::subrange<_Ip, _Sp, _Kp>> { 259e78f53d1SNikolas Klauser using type = _Ip; 260e78f53d1SNikolas Klauser }; 261e78f53d1SNikolas Klauser 262e78f53d1SNikolas Klauser template <class _Ip, class _Sp, ranges::subrange_kind _Kp> 263e78f53d1SNikolas Klauser struct tuple_element<1, const ranges::subrange<_Ip, _Sp, _Kp>> { 264e78f53d1SNikolas Klauser using type = _Sp; 265e78f53d1SNikolas Klauser }; 266e78f53d1SNikolas Klauser 267e78f53d1SNikolas Klauser #endif // _LIBCPP_STD_VER >= 20 268e78f53d1SNikolas Klauser 269e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD 270e78f53d1SNikolas Klauser 271e78f53d1SNikolas Klauser _LIBCPP_POP_MACROS 272e78f53d1SNikolas Klauser 273*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___RANGES_SUBRANGE_H 274