1349cc55cSDimitry Andric // -*- C++ -*- 2349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 3349cc55cSDimitry Andric // 4349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7349cc55cSDimitry Andric // 8349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 9bdd1243dSDimitry Andric 10349cc55cSDimitry Andric #ifndef _LIBCPP___RANGES_JOIN_VIEW_H 11349cc55cSDimitry Andric #define _LIBCPP___RANGES_JOIN_VIEW_H 12349cc55cSDimitry Andric 1381ad6265SDimitry Andric #include <__concepts/constructible.h> 1481ad6265SDimitry Andric #include <__concepts/convertible_to.h> 1581ad6265SDimitry Andric #include <__concepts/copyable.h> 1681ad6265SDimitry Andric #include <__concepts/derived_from.h> 1781ad6265SDimitry Andric #include <__concepts/equality_comparable.h> 18349cc55cSDimitry Andric #include <__config> 19349cc55cSDimitry Andric #include <__iterator/concepts.h> 2081ad6265SDimitry Andric #include <__iterator/iter_move.h> 2181ad6265SDimitry Andric #include <__iterator/iter_swap.h> 22349cc55cSDimitry Andric #include <__iterator/iterator_traits.h> 23bdd1243dSDimitry Andric #include <__iterator/iterator_with_data.h> 24bdd1243dSDimitry Andric #include <__iterator/segmented_iterator.h> 2506c3fb27SDimitry Andric #include <__memory/addressof.h> 26349cc55cSDimitry Andric #include <__ranges/access.h> 27349cc55cSDimitry Andric #include <__ranges/all.h> 28349cc55cSDimitry Andric #include <__ranges/concepts.h> 29bdd1243dSDimitry Andric #include <__ranges/empty.h> 30349cc55cSDimitry Andric #include <__ranges/non_propagating_cache.h> 3181ad6265SDimitry Andric #include <__ranges/range_adaptor.h> 32349cc55cSDimitry Andric #include <__ranges/view_interface.h> 3306c3fb27SDimitry Andric #include <__type_traits/common_type.h> 34bdd1243dSDimitry Andric #include <__type_traits/maybe_const.h> 355f757f3fSDimitry Andric #include <__utility/as_lvalue.h> 365f757f3fSDimitry Andric #include <__utility/empty.h> 37349cc55cSDimitry Andric #include <__utility/forward.h> 38349cc55cSDimitry Andric #include <optional> 39349cc55cSDimitry Andric 40349cc55cSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 41349cc55cSDimitry Andric # pragma GCC system_header 42349cc55cSDimitry Andric #endif 43349cc55cSDimitry Andric 44*b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS 45*b3edf446SDimitry Andric #include <__undef_macros> 46*b3edf446SDimitry Andric 47349cc55cSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 48349cc55cSDimitry Andric 495f757f3fSDimitry Andric #if _LIBCPP_STD_VER >= 20 50349cc55cSDimitry Andric 51349cc55cSDimitry Andric namespace ranges { 52349cc55cSDimitry Andric template <class> 53349cc55cSDimitry Andric struct __join_view_iterator_category {}; 54349cc55cSDimitry Andric 55349cc55cSDimitry Andric template <class _View> 56cb14a3feSDimitry Andric requires is_reference_v<range_reference_t<_View>> && forward_range<_View> && forward_range<range_reference_t<_View>> 57349cc55cSDimitry Andric struct __join_view_iterator_category<_View> { 58349cc55cSDimitry Andric using _OuterC = typename iterator_traits<iterator_t<_View>>::iterator_category; 59349cc55cSDimitry Andric using _InnerC = typename iterator_traits<iterator_t<range_reference_t<_View>>>::iterator_category; 60349cc55cSDimitry Andric 61cb14a3feSDimitry Andric using iterator_category = 62cb14a3feSDimitry Andric _If< derived_from<_OuterC, bidirectional_iterator_tag> && derived_from<_InnerC, bidirectional_iterator_tag> && 6381ad6265SDimitry Andric common_range<range_reference_t<_View>>, 64349cc55cSDimitry Andric bidirectional_iterator_tag, 65cb14a3feSDimitry Andric _If< derived_from<_OuterC, forward_iterator_tag> && derived_from<_InnerC, forward_iterator_tag>, 66349cc55cSDimitry Andric forward_iterator_tag, 67cb14a3feSDimitry Andric input_iterator_tag > >; 68349cc55cSDimitry Andric }; 69349cc55cSDimitry Andric 70349cc55cSDimitry Andric template <input_range _View> 71349cc55cSDimitry Andric requires view<_View> && input_range<range_reference_t<_View>> 72cb14a3feSDimitry Andric class join_view : public view_interface<join_view<_View>> { 73349cc55cSDimitry Andric private: 74349cc55cSDimitry Andric using _InnerRange = range_reference_t<_View>; 75349cc55cSDimitry Andric 76cb14a3feSDimitry Andric template <bool> 77cb14a3feSDimitry Andric struct __iterator; 78bdd1243dSDimitry Andric 79cb14a3feSDimitry Andric template <bool> 80cb14a3feSDimitry Andric struct __sentinel; 81bdd1243dSDimitry Andric 82bdd1243dSDimitry Andric template <class> 83bdd1243dSDimitry Andric friend struct std::__segmented_iterator_traits; 84349cc55cSDimitry Andric 8581ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); 86349cc55cSDimitry Andric 875f757f3fSDimitry Andric static constexpr bool _UseOuterCache = !forward_range<_View>; 885f757f3fSDimitry Andric using _OuterCache = _If<_UseOuterCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; 895f757f3fSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _OuterCache __outer_; 905f757f3fSDimitry Andric 915f757f3fSDimitry Andric static constexpr bool _UseInnerCache = !is_reference_v<_InnerRange>; 925f757f3fSDimitry Andric using _InnerCache = _If<_UseInnerCache, __non_propagating_cache<remove_cvref_t<_InnerRange>>, __empty_cache>; 935f757f3fSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _InnerCache __inner_; 945f757f3fSDimitry Andric 95349cc55cSDimitry Andric public: 96cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI join_view() 97cb14a3feSDimitry Andric requires default_initializable<_View> 98cb14a3feSDimitry Andric = default; 99349cc55cSDimitry Andric 100cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit join_view(_View __base) : __base_(std::move(__base)) {} 101349cc55cSDimitry Andric 102cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& 103cb14a3feSDimitry Andric requires copy_constructible<_View> 104cb14a3feSDimitry Andric { 105cb14a3feSDimitry Andric return __base_; 106cb14a3feSDimitry Andric } 107349cc55cSDimitry Andric 108cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } 109349cc55cSDimitry Andric 110cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto begin() { 1115f757f3fSDimitry Andric if constexpr (forward_range<_View>) { 112cb14a3feSDimitry Andric constexpr bool __use_const = __simple_view<_View> && is_reference_v<range_reference_t<_View>>; 113349cc55cSDimitry Andric return __iterator<__use_const>{*this, ranges::begin(__base_)}; 1145f757f3fSDimitry Andric } else { 1155f757f3fSDimitry Andric __outer_.__emplace(ranges::begin(__base_)); 1165f757f3fSDimitry Andric return __iterator<false>{*this}; 1175f757f3fSDimitry Andric } 118349cc55cSDimitry Andric } 119349cc55cSDimitry Andric 120349cc55cSDimitry Andric template <class _V2 = _View> 121cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const 122cb14a3feSDimitry Andric requires forward_range<const _V2> && is_reference_v<range_reference_t<const _V2>> && 1235f757f3fSDimitry Andric input_range<range_reference_t<const _V2>> 124349cc55cSDimitry Andric { 125349cc55cSDimitry Andric return __iterator<true>{*this, ranges::begin(__base_)}; 126349cc55cSDimitry Andric } 127349cc55cSDimitry Andric 128cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto end() { 129cb14a3feSDimitry Andric if constexpr (forward_range<_View> && is_reference_v<_InnerRange> && forward_range<_InnerRange> && 130cb14a3feSDimitry Andric common_range<_View> && common_range<_InnerRange>) 131349cc55cSDimitry Andric return __iterator<__simple_view<_View>>{*this, ranges::end(__base_)}; 132349cc55cSDimitry Andric else 133349cc55cSDimitry Andric return __sentinel<__simple_view<_View>>{*this}; 134349cc55cSDimitry Andric } 135349cc55cSDimitry Andric 136349cc55cSDimitry Andric template <class _V2 = _View> 137cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto end() const 138cb14a3feSDimitry Andric requires forward_range<const _V2> && is_reference_v<range_reference_t<const _V2>> && 1395f757f3fSDimitry Andric input_range<range_reference_t<const _V2>> 140349cc55cSDimitry Andric { 141349cc55cSDimitry Andric using _ConstInnerRange = range_reference_t<const _View>; 142cb14a3feSDimitry Andric if constexpr (forward_range<_ConstInnerRange> && common_range<const _View> && common_range<_ConstInnerRange>) { 143349cc55cSDimitry Andric return __iterator<true>{*this, ranges::end(__base_)}; 144349cc55cSDimitry Andric } else { 145349cc55cSDimitry Andric return __sentinel<true>{*this}; 146349cc55cSDimitry Andric } 147349cc55cSDimitry Andric } 148349cc55cSDimitry Andric }; 149349cc55cSDimitry Andric 1501ac55f4cSDimitry Andric template <input_range _View> 151349cc55cSDimitry Andric requires view<_View> && input_range<range_reference_t<_View>> 1521ac55f4cSDimitry Andric template <bool _Const> 1531ac55f4cSDimitry Andric struct join_view<_View>::__sentinel { 1545f757f3fSDimitry Andric private: 1551ac55f4cSDimitry Andric template <bool> 1561ac55f4cSDimitry Andric friend struct __sentinel; 157349cc55cSDimitry Andric 1585f757f3fSDimitry Andric using _Parent = __maybe_const<_Const, join_view>; 159349cc55cSDimitry Andric using _Base = __maybe_const<_Const, _View>; 160349cc55cSDimitry Andric sentinel_t<_Base> __end_ = sentinel_t<_Base>(); 161349cc55cSDimitry Andric 162349cc55cSDimitry Andric public: 163cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __sentinel() = default; 164349cc55cSDimitry Andric 165cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(_Parent& __parent) : __end_(ranges::end(__parent.__base_)) {} 166349cc55cSDimitry Andric 167cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s) 168349cc55cSDimitry Andric requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> 16981ad6265SDimitry Andric : __end_(std::move(__s.__end_)) {} 170349cc55cSDimitry Andric 171349cc55cSDimitry Andric template <bool _OtherConst> 172349cc55cSDimitry Andric requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> 173cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { 1745f757f3fSDimitry Andric return __x.__get_outer() == __y.__end_; 175349cc55cSDimitry Andric } 176349cc55cSDimitry Andric }; 177349cc55cSDimitry Andric 1781ac55f4cSDimitry Andric // https://reviews.llvm.org/D142811#inline-1383022 1791ac55f4cSDimitry Andric // To simplify the segmented iterator traits specialization, 1801ac55f4cSDimitry Andric // make the iterator `final` 1811ac55f4cSDimitry Andric template <input_range _View> 182349cc55cSDimitry Andric requires view<_View> && input_range<range_reference_t<_View>> 1831ac55f4cSDimitry Andric template <bool _Const> 184cb14a3feSDimitry Andric struct join_view<_View>::__iterator final : public __join_view_iterator_category<__maybe_const<_Const, _View>> { 1855f757f3fSDimitry Andric friend join_view; 186bdd1243dSDimitry Andric 187bdd1243dSDimitry Andric template <class> 188bdd1243dSDimitry Andric friend struct std::__segmented_iterator_traits; 189349cc55cSDimitry Andric 1901ac55f4cSDimitry Andric static constexpr bool __is_join_view_iterator = true; 1911ac55f4cSDimitry Andric 192349cc55cSDimitry Andric private: 193bdd1243dSDimitry Andric using _Parent = __maybe_const<_Const, join_view<_View>>; 194349cc55cSDimitry Andric using _Base = __maybe_const<_Const, _View>; 195349cc55cSDimitry Andric using _Outer = iterator_t<_Base>; 196349cc55cSDimitry Andric using _Inner = iterator_t<range_reference_t<_Base>>; 197bdd1243dSDimitry Andric using _InnerRange = range_reference_t<_View>; 198349cc55cSDimitry Andric 1995f757f3fSDimitry Andric static_assert(!_Const || forward_range<_Base>, "Const can only be true when Base models forward_range."); 2005f757f3fSDimitry Andric 201349cc55cSDimitry Andric static constexpr bool __ref_is_glvalue = is_reference_v<range_reference_t<_Base>>; 202349cc55cSDimitry Andric 2035f757f3fSDimitry Andric static constexpr bool _OuterPresent = forward_range<_Base>; 2045f757f3fSDimitry Andric using _OuterType = _If<_OuterPresent, _Outer, std::__empty>; 2055f757f3fSDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS _OuterType __outer_ = _OuterType(); 206349cc55cSDimitry Andric 207349cc55cSDimitry Andric optional<_Inner> __inner_; 208349cc55cSDimitry Andric _Parent* __parent_ = nullptr; 209349cc55cSDimitry Andric 210cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __satisfy() { 2115f757f3fSDimitry Andric for (; __get_outer() != ranges::end(__parent_->__base_); ++__get_outer()) { 2125f757f3fSDimitry Andric auto&& __inner = [this]() -> auto&& { 213349cc55cSDimitry Andric if constexpr (__ref_is_glvalue) 2145f757f3fSDimitry Andric return *__get_outer(); 215349cc55cSDimitry Andric else 2165f757f3fSDimitry Andric return __parent_->__inner_.__emplace_from([&]() -> decltype(auto) { return *__get_outer(); }); 217349cc55cSDimitry Andric }(); 218349cc55cSDimitry Andric __inner_ = ranges::begin(__inner); 219349cc55cSDimitry Andric if (*__inner_ != ranges::end(__inner)) 220349cc55cSDimitry Andric return; 221349cc55cSDimitry Andric } 222349cc55cSDimitry Andric 223349cc55cSDimitry Andric if constexpr (__ref_is_glvalue) 224349cc55cSDimitry Andric __inner_.reset(); 225349cc55cSDimitry Andric } 226349cc55cSDimitry Andric 2275f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Outer& __get_outer() { 2285f757f3fSDimitry Andric if constexpr (forward_range<_Base>) { 2295f757f3fSDimitry Andric return __outer_; 2305f757f3fSDimitry Andric } else { 2315f757f3fSDimitry Andric return *__parent_->__outer_; 2325f757f3fSDimitry Andric } 2335f757f3fSDimitry Andric } 2345f757f3fSDimitry Andric 2355f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr const _Outer& __get_outer() const { 2365f757f3fSDimitry Andric if constexpr (forward_range<_Base>) { 2375f757f3fSDimitry Andric return __outer_; 2385f757f3fSDimitry Andric } else { 2395f757f3fSDimitry Andric return *__parent_->__outer_; 2405f757f3fSDimitry Andric } 2415f757f3fSDimitry Andric } 2425f757f3fSDimitry Andric 2435f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent& __parent, _Outer __outer) 2445f757f3fSDimitry Andric requires forward_range<_Base> 2455f757f3fSDimitry Andric : __outer_(std::move(__outer)), __parent_(std::addressof(__parent)) { 2465f757f3fSDimitry Andric __satisfy(); 2475f757f3fSDimitry Andric } 2485f757f3fSDimitry Andric 2495f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(_Parent& __parent) 2505f757f3fSDimitry Andric requires(!forward_range<_Base>) 2515f757f3fSDimitry Andric : __parent_(std::addressof(__parent)) { 2525f757f3fSDimitry Andric __satisfy(); 2535f757f3fSDimitry Andric } 2545f757f3fSDimitry Andric 2551ac55f4cSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent* __parent, _Outer __outer, _Inner __inner) 2565f757f3fSDimitry Andric requires forward_range<_Base> 257bdd1243dSDimitry Andric : __outer_(std::move(__outer)), __inner_(std::move(__inner)), __parent_(__parent) {} 258bdd1243dSDimitry Andric 259349cc55cSDimitry Andric public: 260cb14a3feSDimitry Andric using iterator_concept = 261cb14a3feSDimitry Andric _If< __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && 26281ad6265SDimitry Andric common_range<range_reference_t<_Base>>, 263349cc55cSDimitry Andric bidirectional_iterator_tag, 264cb14a3feSDimitry Andric _If< __ref_is_glvalue && forward_range<_Base> && forward_range<range_reference_t<_Base>>, 265349cc55cSDimitry Andric forward_iterator_tag, 266cb14a3feSDimitry Andric input_iterator_tag > >; 267349cc55cSDimitry Andric 268349cc55cSDimitry Andric using value_type = range_value_t<range_reference_t<_Base>>; 269349cc55cSDimitry Andric 270cb14a3feSDimitry Andric using difference_type = common_type_t< range_difference_t<_Base>, range_difference_t<range_reference_t<_Base>>>; 271349cc55cSDimitry Andric 2725f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator() = default; 273349cc55cSDimitry Andric 274cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i) 275cb14a3feSDimitry Andric requires _Const && convertible_to<iterator_t<_View>, _Outer> && convertible_to<iterator_t<_InnerRange>, _Inner> 276cb14a3feSDimitry Andric : __outer_(std::move(__i.__outer_)), __inner_(std::move(__i.__inner_)), __parent_(__i.__parent_) {} 277349cc55cSDimitry Andric 278cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return **__inner_; } 279349cc55cSDimitry Andric 280cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Inner operator->() const 281349cc55cSDimitry Andric requires __has_arrow<_Inner> && copyable<_Inner> 282349cc55cSDimitry Andric { 283349cc55cSDimitry Andric return *__inner_; 284349cc55cSDimitry Andric } 285349cc55cSDimitry Andric 286cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { 2875f757f3fSDimitry Andric auto __get_inner_range = [&]() -> decltype(auto) { 288349cc55cSDimitry Andric if constexpr (__ref_is_glvalue) 2895f757f3fSDimitry Andric return *__get_outer(); 290349cc55cSDimitry Andric else 2915f757f3fSDimitry Andric return *__parent_->__inner_; 2925f757f3fSDimitry Andric }; 2935f757f3fSDimitry Andric if (++*__inner_ == ranges::end(std::__as_lvalue(__get_inner_range()))) { 2945f757f3fSDimitry Andric ++__get_outer(); 295349cc55cSDimitry Andric __satisfy(); 296349cc55cSDimitry Andric } 297349cc55cSDimitry Andric return *this; 298349cc55cSDimitry Andric } 299349cc55cSDimitry Andric 300cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; } 301349cc55cSDimitry Andric 302cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) 303cb14a3feSDimitry Andric requires __ref_is_glvalue && forward_range<_Base> && forward_range<range_reference_t<_Base>> 304349cc55cSDimitry Andric { 305349cc55cSDimitry Andric auto __tmp = *this; 306349cc55cSDimitry Andric ++*this; 307349cc55cSDimitry Andric return __tmp; 308349cc55cSDimitry Andric } 309349cc55cSDimitry Andric 310cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() 311cb14a3feSDimitry Andric requires __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && 312349cc55cSDimitry Andric common_range<range_reference_t<_Base>> 313349cc55cSDimitry Andric { 314349cc55cSDimitry Andric if (__outer_ == ranges::end(__parent_->__base_)) 3155f757f3fSDimitry Andric __inner_ = ranges::end(std::__as_lvalue(*--__outer_)); 316349cc55cSDimitry Andric 317349cc55cSDimitry Andric // Skip empty inner ranges when going backwards. 3185f757f3fSDimitry Andric while (*__inner_ == ranges::begin(std::__as_lvalue(*__outer_))) { 3195f757f3fSDimitry Andric __inner_ = ranges::end(std::__as_lvalue(*--__outer_)); 320349cc55cSDimitry Andric } 321349cc55cSDimitry Andric 322349cc55cSDimitry Andric --*__inner_; 323349cc55cSDimitry Andric return *this; 324349cc55cSDimitry Andric } 325349cc55cSDimitry Andric 326cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) 327cb14a3feSDimitry Andric requires __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range<range_reference_t<_Base>> && 328349cc55cSDimitry Andric common_range<range_reference_t<_Base>> 329349cc55cSDimitry Andric { 330349cc55cSDimitry Andric auto __tmp = *this; 331349cc55cSDimitry Andric --*this; 332349cc55cSDimitry Andric return __tmp; 333349cc55cSDimitry Andric } 334349cc55cSDimitry Andric 335cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) 336cb14a3feSDimitry Andric requires __ref_is_glvalue && forward_range<_Base> && equality_comparable<iterator_t<range_reference_t<_Base>>> 337349cc55cSDimitry Andric { 338349cc55cSDimitry Andric return __x.__outer_ == __y.__outer_ && __x.__inner_ == __y.__inner_; 339349cc55cSDimitry Andric } 340349cc55cSDimitry Andric 341cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr decltype(auto) 342cb14a3feSDimitry Andric iter_move(const __iterator& __i) noexcept(noexcept(ranges::iter_move(*__i.__inner_))) { 343349cc55cSDimitry Andric return ranges::iter_move(*__i.__inner_); 344349cc55cSDimitry Andric } 345349cc55cSDimitry Andric 346cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr void 347cb14a3feSDimitry Andric iter_swap(const __iterator& __x, 348cb14a3feSDimitry Andric const __iterator& __y) noexcept(noexcept(ranges::iter_swap(*__x.__inner_, *__y.__inner_))) 349349cc55cSDimitry Andric requires indirectly_swappable<_Inner> 350349cc55cSDimitry Andric { 351349cc55cSDimitry Andric return ranges::iter_swap(*__x.__inner_, *__y.__inner_); 352349cc55cSDimitry Andric } 353349cc55cSDimitry Andric }; 354349cc55cSDimitry Andric 355349cc55cSDimitry Andric template <class _Range> 356349cc55cSDimitry Andric explicit join_view(_Range&&) -> join_view<views::all_t<_Range>>; 357349cc55cSDimitry Andric 35881ad6265SDimitry Andric namespace views { 35981ad6265SDimitry Andric namespace __join_view { 36081ad6265SDimitry Andric struct __fn : __range_adaptor_closure<__fn> { 36181ad6265SDimitry Andric template <class _Range> 362cb14a3feSDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const 36381ad6265SDimitry Andric noexcept(noexcept(join_view<all_t<_Range&&>>(std::forward<_Range>(__range)))) 364cb14a3feSDimitry Andric -> decltype(join_view<all_t<_Range&&>>(std::forward<_Range>(__range))) { 365cb14a3feSDimitry Andric return join_view<all_t<_Range&&>>(std::forward<_Range>(__range)); 366cb14a3feSDimitry Andric } 36781ad6265SDimitry Andric }; 36881ad6265SDimitry Andric } // namespace __join_view 36981ad6265SDimitry Andric inline namespace __cpo { 37081ad6265SDimitry Andric inline constexpr auto join = __join_view::__fn{}; 37181ad6265SDimitry Andric } // namespace __cpo 37281ad6265SDimitry Andric } // namespace views 373349cc55cSDimitry Andric } // namespace ranges 374349cc55cSDimitry Andric 3751ac55f4cSDimitry Andric template <class _JoinViewIterator> 376cb14a3feSDimitry Andric requires(_JoinViewIterator::__is_join_view_iterator && ranges::common_range<typename _JoinViewIterator::_Parent> && 37706c3fb27SDimitry Andric __has_random_access_iterator_category<typename _JoinViewIterator::_Outer>::value && 37806c3fb27SDimitry Andric __has_random_access_iterator_category<typename _JoinViewIterator::_Inner>::value) 3791ac55f4cSDimitry Andric struct __segmented_iterator_traits<_JoinViewIterator> { 380bdd1243dSDimitry Andric using __segment_iterator = 381bdd1243dSDimitry Andric _LIBCPP_NODEBUG __iterator_with_data<typename _JoinViewIterator::_Outer, typename _JoinViewIterator::_Parent*>; 382bdd1243dSDimitry Andric using __local_iterator = typename _JoinViewIterator::_Inner; 383bdd1243dSDimitry Andric 384bdd1243dSDimitry Andric // TODO: Would it make sense to enable the optimization for other iterator types? 385bdd1243dSDimitry Andric 386bdd1243dSDimitry Andric static constexpr _LIBCPP_HIDE_FROM_ABI __segment_iterator __segment(_JoinViewIterator __iter) { 387bdd1243dSDimitry Andric if (ranges::empty(__iter.__parent_->__base_)) 388bdd1243dSDimitry Andric return {}; 389bdd1243dSDimitry Andric if (!__iter.__inner_.has_value()) 390bdd1243dSDimitry Andric return __segment_iterator(--__iter.__outer_, __iter.__parent_); 391bdd1243dSDimitry Andric return __segment_iterator(__iter.__outer_, __iter.__parent_); 392bdd1243dSDimitry Andric } 393bdd1243dSDimitry Andric 394bdd1243dSDimitry Andric static constexpr _LIBCPP_HIDE_FROM_ABI __local_iterator __local(_JoinViewIterator __iter) { 395bdd1243dSDimitry Andric if (ranges::empty(__iter.__parent_->__base_)) 396bdd1243dSDimitry Andric return {}; 397bdd1243dSDimitry Andric if (!__iter.__inner_.has_value()) 398bdd1243dSDimitry Andric return ranges::end(*--__iter.__outer_); 399bdd1243dSDimitry Andric return *__iter.__inner_; 400bdd1243dSDimitry Andric } 401bdd1243dSDimitry Andric 402bdd1243dSDimitry Andric static constexpr _LIBCPP_HIDE_FROM_ABI __local_iterator __begin(__segment_iterator __iter) { 403bdd1243dSDimitry Andric return ranges::begin(*__iter.__get_iter()); 404bdd1243dSDimitry Andric } 405bdd1243dSDimitry Andric 406bdd1243dSDimitry Andric static constexpr _LIBCPP_HIDE_FROM_ABI __local_iterator __end(__segment_iterator __iter) { 407bdd1243dSDimitry Andric return ranges::end(*__iter.__get_iter()); 408bdd1243dSDimitry Andric } 409bdd1243dSDimitry Andric 410bdd1243dSDimitry Andric static constexpr _LIBCPP_HIDE_FROM_ABI _JoinViewIterator 411bdd1243dSDimitry Andric __compose(__segment_iterator __seg_iter, __local_iterator __local_iter) { 412bdd1243dSDimitry Andric return _JoinViewIterator( 413bdd1243dSDimitry Andric std::move(__seg_iter).__get_data(), std::move(__seg_iter).__get_iter(), std::move(__local_iter)); 414bdd1243dSDimitry Andric } 415bdd1243dSDimitry Andric }; 416bdd1243dSDimitry Andric 4175f757f3fSDimitry Andric #endif // #if _LIBCPP_STD_VER >= 20 418349cc55cSDimitry Andric 419349cc55cSDimitry Andric _LIBCPP_END_NAMESPACE_STD 420349cc55cSDimitry Andric 421*b3edf446SDimitry Andric _LIBCPP_POP_MACROS 422*b3edf446SDimitry Andric 423349cc55cSDimitry Andric #endif // _LIBCPP___RANGES_JOIN_VIEW_H 424