Path: blob/main/contrib/llvm-project/libcxx/include/__ranges/subrange.h
35236 views
// -*- C++ -*-1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//89#ifndef _LIBCPP___RANGES_SUBRANGE_H10#define _LIBCPP___RANGES_SUBRANGE_H1112#include <__assert>13#include <__concepts/constructible.h>14#include <__concepts/convertible_to.h>15#include <__concepts/copyable.h>16#include <__concepts/derived_from.h>17#include <__concepts/different_from.h>18#include <__config>19#include <__fwd/subrange.h>20#include <__iterator/advance.h>21#include <__iterator/concepts.h>22#include <__iterator/incrementable_traits.h>23#include <__iterator/iterator_traits.h>24#include <__ranges/access.h>25#include <__ranges/concepts.h>26#include <__ranges/dangling.h>27#include <__ranges/enable_borrowed_range.h>28#include <__ranges/size.h>29#include <__ranges/view_interface.h>30#include <__tuple/tuple_element.h>31#include <__tuple/tuple_like_no_subrange.h>32#include <__tuple/tuple_size.h>33#include <__type_traits/conditional.h>34#include <__type_traits/decay.h>35#include <__type_traits/is_pointer.h>36#include <__type_traits/is_reference.h>37#include <__type_traits/make_unsigned.h>38#include <__type_traits/remove_const.h>39#include <__type_traits/remove_pointer.h>40#include <__utility/move.h>41#include <cstddef>4243#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)44# pragma GCC system_header45#endif4647_LIBCPP_PUSH_MACROS48#include <__undef_macros>4950_LIBCPP_BEGIN_NAMESPACE_STD5152#if _LIBCPP_STD_VER >= 205354namespace ranges {55template <class _From, class _To>56concept __uses_nonqualification_pointer_conversion =57is_pointer_v<_From> && is_pointer_v<_To> &&58!convertible_to<remove_pointer_t<_From> (*)[], remove_pointer_t<_To> (*)[]>;5960template <class _From, class _To>61concept __convertible_to_non_slicing =62convertible_to<_From, _To> && !__uses_nonqualification_pointer_conversion<decay_t<_From>, decay_t<_To>>;6364template <class _Pair, class _Iter, class _Sent>65concept __pair_like_convertible_from =66!range<_Pair> && __pair_like_no_subrange<_Pair> && constructible_from<_Pair, _Iter, _Sent> &&67__convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> && convertible_to<_Sent, tuple_element_t<1, _Pair>>;6869template <input_or_output_iterator _Iter,70sentinel_for<_Iter> _Sent = _Iter,71subrange_kind _Kind = sized_sentinel_for<_Sent, _Iter> ? subrange_kind::sized : subrange_kind::unsized>72requires(_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>)73class _LIBCPP_TEMPLATE_VIS subrange : public view_interface<subrange<_Iter, _Sent, _Kind>> {74public:75// Note: this is an internal implementation detail that is public only for internal usage.76static constexpr bool _StoreSize = (_Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>);7778private:79static constexpr bool _MustProvideSizeAtConstruction = !_StoreSize; // just to improve compiler diagnostics80struct _Empty {81_LIBCPP_HIDE_FROM_ABI constexpr _Empty(auto) noexcept {}82};83using _Size = conditional_t<_StoreSize, make_unsigned_t<iter_difference_t<_Iter>>, _Empty>;84_LIBCPP_NO_UNIQUE_ADDRESS _Iter __begin_ = _Iter();85_LIBCPP_NO_UNIQUE_ADDRESS _Sent __end_ = _Sent();86_LIBCPP_NO_UNIQUE_ADDRESS _Size __size_ = 0;8788public:89_LIBCPP_HIDE_FROM_ABI subrange()90requires default_initializable<_Iter>91= default;9293_LIBCPP_HIDE_FROM_ABI constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent)94requires _MustProvideSizeAtConstruction95: __begin_(std::move(__iter)), __end_(std::move(__sent)) {}9697_LIBCPP_HIDE_FROM_ABI constexpr subrange(98__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent, make_unsigned_t<iter_difference_t<_Iter>> __n)99requires(_Kind == subrange_kind::sized)100: __begin_(std::move(__iter)), __end_(std::move(__sent)), __size_(__n) {101if constexpr (sized_sentinel_for<_Sent, _Iter>)102_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS((__end_ - __begin_) == static_cast<iter_difference_t<_Iter>>(__n),103"std::ranges::subrange was passed an invalid size hint");104}105106template <__different_from<subrange> _Range>107requires borrowed_range<_Range> && __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&108convertible_to<sentinel_t<_Range>, _Sent>109_LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range)110requires(!_StoreSize)111: subrange(ranges::begin(__range), ranges::end(__range)) {}112113template <__different_from<subrange> _Range>114requires borrowed_range<_Range> && __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&115convertible_to<sentinel_t<_Range>, _Sent>116_LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range)117requires _StoreSize && sized_range<_Range>118: subrange(__range, ranges::size(__range)) {}119120template <borrowed_range _Range>121requires __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&122convertible_to<sentinel_t<_Range>, _Sent>123_LIBCPP_HIDE_FROM_ABI constexpr subrange(_Range&& __range, make_unsigned_t<iter_difference_t<_Iter>> __n)124requires(_Kind == subrange_kind::sized)125: subrange(ranges::begin(__range), ranges::end(__range), __n) {}126127template <__pair_like_convertible_from<const _Iter&, const _Sent&> _Pair>128_LIBCPP_HIDE_FROM_ABI constexpr operator _Pair() const {129return _Pair(__begin_, __end_);130}131132_LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() const133requires copyable<_Iter>134{135return __begin_;136}137138[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin()139requires(!copyable<_Iter>)140{141return std::move(__begin_);142}143144_LIBCPP_HIDE_FROM_ABI constexpr _Sent end() const { return __end_; }145146[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return __begin_ == __end_; }147148_LIBCPP_HIDE_FROM_ABI constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const149requires(_Kind == subrange_kind::sized)150{151if constexpr (_StoreSize)152return __size_;153else154return std::__to_unsigned_like(__end_ - __begin_);155}156157[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) const&158requires forward_iterator<_Iter>159{160auto __tmp = *this;161__tmp.advance(__n);162return __tmp;163}164165[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) && {166advance(__n);167return std::move(*this);168}169170[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange prev(iter_difference_t<_Iter> __n = 1) const171requires bidirectional_iterator<_Iter>172{173auto __tmp = *this;174__tmp.advance(-__n);175return __tmp;176}177178_LIBCPP_HIDE_FROM_ABI constexpr subrange& advance(iter_difference_t<_Iter> __n) {179if constexpr (bidirectional_iterator<_Iter>) {180if (__n < 0) {181ranges::advance(__begin_, __n);182if constexpr (_StoreSize)183__size_ += std::__to_unsigned_like(-__n);184return *this;185}186}187188auto __d = __n - ranges::advance(__begin_, __n, __end_);189if constexpr (_StoreSize)190__size_ -= std::__to_unsigned_like(__d);191return *this;192}193};194195template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>196subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>;197198template <input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>199subrange(_Iter, _Sent, make_unsigned_t<iter_difference_t<_Iter>>) -> subrange<_Iter, _Sent, subrange_kind::sized>;200201template <borrowed_range _Range>202subrange(_Range&&) -> subrange<iterator_t<_Range>,203sentinel_t<_Range>,204(sized_range<_Range> || sized_sentinel_for<sentinel_t<_Range>, iterator_t<_Range>>)205? subrange_kind::sized206: subrange_kind::unsized>;207208template <borrowed_range _Range>209subrange(_Range&&, make_unsigned_t<range_difference_t<_Range>>)210-> subrange<iterator_t<_Range>, sentinel_t<_Range>, subrange_kind::sized>;211212template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>213requires((_Index == 0 && copyable<_Iter>) || _Index == 1)214_LIBCPP_HIDE_FROM_ABI constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) {215if constexpr (_Index == 0)216return __subrange.begin();217else218return __subrange.end();219}220221template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>222requires(_Index < 2)223_LIBCPP_HIDE_FROM_ABI constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) {224if constexpr (_Index == 0)225return __subrange.begin();226else227return __subrange.end();228}229230template <class _Ip, class _Sp, subrange_kind _Kp>231inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true;232233template <range _Rp>234using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp>>, dangling>;235} // namespace ranges236237// [range.subrange.general]238239using ranges::get;240241// [ranges.syn]242243template <class _Ip, class _Sp, ranges::subrange_kind _Kp>244struct tuple_size<ranges::subrange<_Ip, _Sp, _Kp>> : integral_constant<size_t, 2> {};245246template <class _Ip, class _Sp, ranges::subrange_kind _Kp>247struct tuple_element<0, ranges::subrange<_Ip, _Sp, _Kp>> {248using type = _Ip;249};250251template <class _Ip, class _Sp, ranges::subrange_kind _Kp>252struct tuple_element<1, ranges::subrange<_Ip, _Sp, _Kp>> {253using type = _Sp;254};255256template <class _Ip, class _Sp, ranges::subrange_kind _Kp>257struct tuple_element<0, const ranges::subrange<_Ip, _Sp, _Kp>> {258using type = _Ip;259};260261template <class _Ip, class _Sp, ranges::subrange_kind _Kp>262struct tuple_element<1, const ranges::subrange<_Ip, _Sp, _Kp>> {263using type = _Sp;264};265266#endif // _LIBCPP_STD_VER >= 20267268_LIBCPP_END_NAMESPACE_STD269270_LIBCPP_POP_MACROS271272#endif // _LIBCPP___RANGES_SUBRANGE_H273274275