diff --git a/libcxx/include/__ranges/join_view.h b/libcxx/include/__ranges/join_view.h --- a/libcxx/include/__ranges/join_view.h +++ b/libcxx/include/__ranges/join_view.h @@ -66,14 +66,6 @@ >; }; - template - requires view<_View> && input_range> - struct __join_view_iterator; - - template - requires view<_View> && input_range> - struct __join_view_sentinel; - template requires view<_View> && input_range> class join_view @@ -81,19 +73,9 @@ private: using _InnerRange = range_reference_t<_View>; - template - using __iterator = __join_view_iterator<_View, _Const>; + template struct __iterator; - template - using __sentinel = __join_view_sentinel<_View, _Const>; - - template - requires view<_View2> && input_range> - friend struct __join_view_iterator; - - template - requires view<_View2> && input_range> - friend struct __join_view_sentinel; + template struct __sentinel; template friend struct std::__segmented_iterator_traits; @@ -164,12 +146,12 @@ } }; - template + template requires view<_View> && input_range> - struct __join_view_sentinel { - template - requires view<_View2> && input_range> - friend struct __join_view_sentinel; + template + struct join_view<_View>::__sentinel { + template + friend struct __sentinel; private: using _Parent = __maybe_const<_Const, join_view<_View>>; @@ -178,43 +160,58 @@ public: _LIBCPP_HIDE_FROM_ABI - __join_view_sentinel() = default; + __sentinel() = default; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __join_view_sentinel(_Parent& __parent) + constexpr explicit __sentinel(_Parent& __parent) : __end_(ranges::end(__parent.__base_)) {} _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_sentinel(__join_view_sentinel<_View, !_Const> __s) + constexpr __sentinel(__sentinel __s) requires _Const && convertible_to, sentinel_t<_Base>> : __end_(std::move(__s.__end_)) {} template requires sentinel_for, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __join_view_iterator<_View, _OtherConst>& __x, const __join_view_sentinel& __y) { + friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { return __x.__outer_ == __y.__end_; } }; - template + // Make sure that the derived class returns false_type; + struct __is_join_view_iterator_checker { + template + static typename _Tp::_JoinViewIterType __get_type(); + + template + using __check = __enable_if_t<_IsSame<_Tp, decltype(__get_type<_Tp>())>::value>; + }; + + template + using __is_join_view_iterator = _IsValidExpansion<__is_join_view_iterator_checker::__check, _Tp>; + + template requires view<_View> && input_range> - struct __join_view_iterator + template + struct join_view<_View>::__iterator : public __join_view_iterator_category<__maybe_const<_Const, _View>> { - template - requires view<_View2> && input_range> - friend struct __join_view_iterator; + template + friend struct __iterator; template friend struct std::__segmented_iterator_traits; + friend __is_join_view_iterator_checker; + private: using _Parent = __maybe_const<_Const, join_view<_View>>; using _Base = __maybe_const<_Const, _View>; using _Outer = iterator_t<_Base>; using _Inner = iterator_t>; using _InnerRange = range_reference_t<_View>; + using _JoinViewIterType = __iterator; static constexpr bool __ref_is_glvalue = is_reference_v>; @@ -243,7 +240,7 @@ __inner_.reset(); } - _LIBCPP_HIDE_FROM_ABI constexpr __join_view_iterator(_Parent* __parent, _Outer __outer, _Inner __inner) + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent* __parent, _Outer __outer, _Inner __inner) : __outer_(std::move(__outer)), __inner_(std::move(__inner)), __parent_(__parent) {} public: @@ -264,17 +261,17 @@ range_difference_t<_Base>, range_difference_t>>; _LIBCPP_HIDE_FROM_ABI - __join_view_iterator() requires default_initializable<_Outer> = default; + __iterator() requires default_initializable<_Outer> = default; _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator(_Parent& __parent, _Outer __outer) + constexpr __iterator(_Parent& __parent, _Outer __outer) : __outer_(std::move(__outer)) , __parent_(std::addressof(__parent)) { __satisfy(); } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator(__join_view_iterator<_View, !_Const> __i) + constexpr __iterator(__iterator __i) requires _Const && convertible_to, _Outer> && convertible_to, _Inner> @@ -295,7 +292,7 @@ } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator& operator++() { + constexpr __iterator& operator++() { auto&& __inner = [&]() -> auto&& { if constexpr (__ref_is_glvalue) return *__outer_; @@ -315,7 +312,7 @@ } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator operator++(int) + constexpr __iterator operator++(int) requires __ref_is_glvalue && forward_range<_Base> && forward_range> @@ -326,7 +323,7 @@ } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator& operator--() + constexpr __iterator& operator--() requires __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range> && @@ -345,7 +342,7 @@ } _LIBCPP_HIDE_FROM_ABI - constexpr __join_view_iterator operator--(int) + constexpr __iterator operator--(int) requires __ref_is_glvalue && bidirectional_range<_Base> && bidirectional_range> && @@ -357,7 +354,7 @@ } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __join_view_iterator& __x, const __join_view_iterator& __y) + friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) requires __ref_is_glvalue && equality_comparable> && equality_comparable>> @@ -366,14 +363,14 @@ } _LIBCPP_HIDE_FROM_ABI - friend constexpr decltype(auto) iter_move(const __join_view_iterator& __i) + friend constexpr decltype(auto) iter_move(const __iterator& __i) noexcept(noexcept(ranges::iter_move(*__i.__inner_))) { return ranges::iter_move(*__i.__inner_); } _LIBCPP_HIDE_FROM_ABI - friend constexpr void iter_swap(const __join_view_iterator& __x, const __join_view_iterator& __y) + friend constexpr void iter_swap(const __iterator& __x, const __iterator& __y) noexcept(noexcept(ranges::iter_swap(*__x.__inner_, *__y.__inner_))) requires indirectly_swappable<_Inner> { @@ -401,12 +398,12 @@ } // namespace views } // namespace ranges -template - requires(ranges::common_range::_Parent> && - __is_cpp17_random_access_iterator::_Outer>::value && - __is_cpp17_random_access_iterator::_Inner>::value) -struct __segmented_iterator_traits> { - using _JoinViewIterator = ranges::__join_view_iterator<_View, _Const>; +template + requires(ranges::__is_join_view_iterator<_JoinViewIterator>::value && + ranges::common_range && + __is_cpp17_random_access_iterator::value && + __is_cpp17_random_access_iterator::value) +struct __segmented_iterator_traits<_JoinViewIterator> { using __segment_iterator = _LIBCPP_NODEBUG __iterator_with_data; diff --git a/libcxx/test/libcxx/containers/sequences/deque/segmented_iterator.compile.pass.cpp b/libcxx/test/libcxx/containers/sequences/deque/segmented_iterator.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/containers/sequences/deque/segmented_iterator.compile.pass.cpp @@ -0,0 +1,13 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include + + +using DequeIterator = typename std::deque::iterator; +static_assert(std::__is_segmented_iterator::value, ""); diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.join/segmented_iterator.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.join/segmented_iterator.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.join/segmented_iterator.compile.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +#include +#include + +using JoinView = decltype(std::views::join(std::declval>&>())); +using JoinIter = std::ranges::iterator_t; +static_assert(std::__is_segmented_iterator::value); + +struct DerivedIter : JoinIter{}; + +static_assert(!std::__is_segmented_iterator::value);