-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Implement rest of P2259R1, Repairing Input Range Adaptors #2059
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c87ce0f
f7e1671
3be319a
5e89ddc
6e7eace
24f6966
30b155d
c99168d
fab7f47
52cbf13
4cd172d
3069ebf
91aea86
c510f4e
bbe520a
93f942e
1d083ca
0ee79a0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -776,18 +776,36 @@ namespace ranges { | |
| { __j - __j } -> convertible_to<_Iota_diff_t<_Ty>>; | ||
| }; | ||
|
|
||
| template <class _Wi> | ||
| struct _Ioterator_category_base { | ||
| _NODISCARD auto operator<=>(const _Ioterator_category_base&) const = default; | ||
| }; | ||
|
|
||
| template <incrementable _Wi> | ||
| struct _Ioterator_category_base<_Wi> { | ||
| using iterator_category = input_iterator_tag; | ||
|
|
||
| _NODISCARD auto operator<=>(const _Ioterator_category_base&) const = default; | ||
| }; | ||
|
|
||
| template <weakly_incrementable _Wi> | ||
| requires copyable<_Wi> | ||
| struct _Ioterator { | ||
| struct _Ioterator : _Ioterator_category_base<_Wi> { | ||
| // clang-format on | ||
| /* [[no_unique_address]] */ _Wi _Current; | ||
| /* [[no_unique_address]] */ _Wi _Current{}; | ||
|
|
||
| using iterator_concept = conditional_t<_Advanceable<_Wi>, random_access_iterator_tag, | ||
| using iterator_concept = conditional_t<_Advanceable<_Wi>, random_access_iterator_tag, | ||
| conditional_t<_Decrementable<_Wi>, bidirectional_iterator_tag, | ||
| conditional_t<incrementable<_Wi>, forward_iterator_tag, input_iterator_tag>>>; | ||
| using iterator_category = input_iterator_tag; | ||
| using value_type = _Wi; | ||
| using difference_type = _Iota_diff_t<_Wi>; | ||
| using value_type = _Wi; | ||
| using difference_type = _Iota_diff_t<_Wi>; | ||
|
|
||
| // clang-format off | ||
| _Ioterator() requires default_initializable<_Wi> = default; | ||
| // clang-format on | ||
|
|
||
| constexpr explicit _Ioterator(_Wi _Val) noexcept(is_nothrow_move_constructible_v<_Wi>) /* strengthened */ | ||
| : _Current(_STD move(_Val)) {} | ||
|
|
||
| _NODISCARD constexpr _Wi operator*() const noexcept(is_nothrow_copy_constructible_v<_Wi>) { | ||
| return _Current; | ||
|
|
@@ -914,13 +932,11 @@ namespace ranges { | |
| noexcept(!(_Left._Current < _Right._Current))) /* strengthened */ requires totally_ordered<_Wi> { | ||
| return !(_Left._Current < _Right._Current); | ||
| } | ||
|
|
||
| // clang-format off | ||
| _NODISCARD friend constexpr auto operator<=>(const _Ioterator& _Left, const _Ioterator& _Right) noexcept( | ||
| noexcept(_Left._Current <=> _Right._Current)) /* strengthened */ | ||
| requires totally_ordered<_Wi> && three_way_comparable<_Wi> { | ||
| // clang-format on | ||
| return _Left._Current <=> _Right._Current; | ||
| } | ||
| _NODISCARD friend constexpr auto operator<=>(const _Ioterator& _Left, const _Ioterator& _Right) | ||
| requires totally_ordered<_Wi> && three_way_comparable<_Wi> = default; | ||
| // clang-format on | ||
|
|
||
| _NODISCARD friend constexpr _Ioterator operator+(_Ioterator _It, const difference_type _Off) noexcept( | ||
| noexcept(static_cast<_Wi>(_It._Current + _Off))) /* strengthened */ requires _Advanceable<_Wi> { | ||
|
|
@@ -1028,7 +1044,9 @@ namespace ranges { | |
| } | ||
|
|
||
| _NODISCARD constexpr _Se end() const noexcept(is_nothrow_copy_constructible_v<_Bo>) /* strengthened */ { | ||
| if constexpr (same_as<_Bo, unreachable_sentinel_t>) { | ||
| if constexpr (same_as<_Wi, _Bo>) { | ||
| return _It{_Bound}; | ||
| } else if constexpr (same_as<_Bo, unreachable_sentinel_t>) { | ||
| return unreachable_sentinel; | ||
| } else { | ||
| return _Se{_Bound}; | ||
|
|
@@ -1289,20 +1307,20 @@ namespace ranges { | |
| /* [[no_unique_address]] */ _Vw _Range{}; | ||
| /* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred{}; | ||
|
|
||
| template <class _Traits> // TRANSITION, LWG-3289 | ||
| template <class _View> | ||
| struct _Category_base {}; | ||
| // clang-format off | ||
| template <_Has_member_iterator_category _Traits> | ||
| struct _Category_base<_Traits> { | ||
| template <forward_range _View> | ||
| struct _Category_base<_View> { | ||
| // clang-format on | ||
| using iterator_category = | ||
| conditional_t<derived_from<typename _Traits::iterator_category, bidirectional_iterator_tag>, | ||
| conditional_t<derived_from<_Iter_cat_t<iterator_t<_View>>, bidirectional_iterator_tag>, | ||
| bidirectional_iterator_tag, | ||
| conditional_t<derived_from<typename _Traits::iterator_category, forward_iterator_tag>, | ||
| forward_iterator_tag, input_iterator_tag>>; | ||
| conditional_t<derived_from<_Iter_cat_t<iterator_t<_View>>, forward_iterator_tag>, | ||
| forward_iterator_tag, _Iter_cat_t<iterator_t<_View>>>>; | ||
| }; | ||
|
|
||
| class _Iterator : public _Category_base<iterator_traits<iterator_t<_Vw>>> { | ||
| class _Iterator : public _Category_base<_Vw> { | ||
| private: | ||
| /* [[no_unique_address]] */ iterator_t<_Vw> _Current{}; | ||
| filter_view* _Parent{}; | ||
|
|
@@ -1574,21 +1592,21 @@ namespace ranges { | |
| template <bool _Const> | ||
| class _Sentinel; | ||
|
|
||
| template <class _Traits, class _Base> // TRANSITION, LWG-3289 | ||
| template <class _Base> | ||
| struct _Category_base {}; | ||
| // clang-format off | ||
| template <_Has_member_iterator_category _Traits, class _Base> | ||
| struct _Category_base<_Traits, _Base> { | ||
| template <forward_range _Base> | ||
| struct _Category_base<_Base> { | ||
| // clang-format on | ||
| using iterator_category = | ||
| conditional_t<is_lvalue_reference_v<invoke_result_t<_Fn&, range_reference_t<_Base>>>, | ||
| conditional_t<derived_from<typename _Traits::iterator_category, contiguous_iterator_tag>, | ||
| random_access_iterator_tag, typename _Traits::iterator_category>, | ||
| conditional_t<derived_from<_Iter_cat_t<iterator_t<_Base>>, contiguous_iterator_tag>, | ||
| random_access_iterator_tag, _Iter_cat_t<iterator_t<_Base>>>, | ||
| input_iterator_tag>; | ||
| }; | ||
|
|
||
| template <bool _Const> | ||
| class _Iterator : public _Category_base<iterator_traits<iterator_t<_Vw>>, _Maybe_const<_Const, _Vw>> { | ||
| class _Iterator : public _Category_base<_Maybe_const<_Const, _Vw>> { | ||
| private: | ||
| template <bool> | ||
| friend class _Iterator; | ||
|
|
@@ -2902,34 +2920,24 @@ namespace ranges { | |
| template <bool _Const> | ||
| class _Sentinel; | ||
|
|
||
| template <class _OuterTraits, class _InnerTraits, bool _Deref_is_glvalue, | ||
| bool _Inner_common> // TRANSITION, LWG-3289 | ||
| template <class _Outer, class _Inner, bool _Deref_is_glvalue> | ||
| struct _Category_base {}; | ||
|
|
||
| // clang-format off | ||
| template <class _OuterTraits, class _InnerTraits, bool _Deref_is_glvalue, bool _Inner_common> | ||
| requires _Has_member_iterator_category<_OuterTraits> && _Has_member_iterator_category<_InnerTraits> | ||
| struct _Category_base<_OuterTraits, _InnerTraits, _Deref_is_glvalue, _Inner_common> { | ||
| template <forward_range _Outer, forward_range _Inner> | ||
| struct _Category_base<_Outer, _Inner, true> { | ||
| using iterator_category = | ||
| conditional_t<_Deref_is_glvalue && _Inner_common // per LWG issue unnumbered as of 2021-03-16 | ||
| && derived_from<typename _OuterTraits::iterator_category, bidirectional_iterator_tag> | ||
| && derived_from<typename _InnerTraits::iterator_category, bidirectional_iterator_tag>, | ||
| conditional_t<common_range<_Inner> // per LWG-3535 | ||
| && derived_from<_Iter_cat_t<iterator_t<_Outer>>, bidirectional_iterator_tag> // | ||
| && derived_from<_Iter_cat_t<iterator_t<_Inner>>, bidirectional_iterator_tag>, | ||
| bidirectional_iterator_tag, | ||
| conditional_t<_Deref_is_glvalue | ||
| && derived_from<typename _OuterTraits::iterator_category, forward_iterator_tag> | ||
| && derived_from<typename _InnerTraits::iterator_category, forward_iterator_tag>, | ||
| forward_iterator_tag, | ||
| conditional_t<derived_from<typename _OuterTraits::iterator_category, input_iterator_tag> | ||
| && derived_from<typename _InnerTraits::iterator_category, input_iterator_tag>, | ||
| input_iterator_tag, | ||
| output_iterator_tag>>>; | ||
| conditional_t<derived_from<_Iter_cat_t<iterator_t<_Outer>>, forward_iterator_tag> // | ||
| && derived_from<_Iter_cat_t<iterator_t<_Inner>>, forward_iterator_tag>, | ||
| forward_iterator_tag, input_iterator_tag>>; | ||
| }; | ||
| // clang-format on | ||
|
|
||
| template <bool _Const> | ||
| class _Iterator : public _Category_base<iterator_traits<iterator_t<_Maybe_const<_Const, _Vw>>>, | ||
| iterator_traits<iterator_t<_InnerRng<_Const>>>, is_reference_v<_InnerRng<_Const>>, | ||
| common_range<_InnerRng<_Const>>> { | ||
| class _Iterator | ||
| : public _Category_base<_Maybe_const<_Const, _Vw>, _InnerRng<_Const>, is_reference_v<_InnerRng<_Const>>> { | ||
| private: | ||
| template <bool> | ||
| friend class _Iterator; | ||
|
|
@@ -3284,10 +3292,8 @@ namespace ranges { | |
| template <class> | ||
| class _Outer_iter_base {}; | ||
|
|
||
| // clang-format off | ||
| template <forward_iterator _Iter> | ||
| class _Outer_iter_base<_Iter> { | ||
| // clang-format on | ||
| protected: | ||
| _Iter _Current{}; | ||
|
|
||
|
|
@@ -4002,18 +4008,20 @@ namespace ranges { | |
| template <bool _Const> | ||
| class _Sentinel; | ||
|
|
||
| template <class _Traits> // TRANSITION, LWG-3289 | ||
| template <class _Base> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note to other reviewers: we already implement the equivalent of the |
||
| struct _Category_base {}; | ||
|
|
||
| // clang-format off | ||
| template <_Has_member_iterator_category _Traits> | ||
| struct _Category_base<_Traits> { | ||
| // clang-format on | ||
| using iterator_category = typename _Traits::iterator_category; | ||
| template <forward_range _Base> | ||
| struct _Category_base<_Base> { | ||
| using iterator_category = | ||
| conditional_t<!is_lvalue_reference_v<decltype(_STD get<_Index>(*_STD declval<iterator_t<_Base>>()))>, | ||
| input_iterator_tag, | ||
| conditional_t<derived_from<_Iter_cat_t<iterator_t<_Base>>, random_access_iterator_tag>, | ||
| random_access_iterator_tag, _Iter_cat_t<iterator_t<_Base>>>>; | ||
| }; | ||
|
|
||
| template <bool _Const> | ||
| class _Iterator : public _Category_base<iterator_traits<iterator_t<_Vw>>> { | ||
| class _Iterator : public _Category_base<_Maybe_const<_Const, _Vw>> { | ||
| private: | ||
| template <bool> | ||
| friend class _Iterator; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -441,8 +441,8 @@ struct _Old_iter_traits_pointer<false> { | |
| template <_Has_iter_types _It> | ||
| struct _Iterator_traits_base<_It> { | ||
| using iterator_category = typename _It::iterator_category; | ||
| using difference_type = typename _It::difference_type; | ||
| using value_type = typename _It::value_type; | ||
| using difference_type = typename _It::difference_type; | ||
| using pointer = typename _Old_iter_traits_pointer<_Has_member_pointer<_It>>::template _Apply<_It>; | ||
| using reference = typename _It::reference; | ||
| }; | ||
|
|
@@ -481,15 +481,12 @@ concept _Cpp17_input_iterator = _Cpp17_iterator<_It> | |
| }; | ||
|
|
||
| template <class _It> | ||
| requires (!_Has_iter_types<_It> && _Cpp17_iterator<_It> && !_Cpp17_input_iterator<_It> | ||
| // Implements the proposed resolution of LWG-3283: | ||
| && (!requires { typename _It::iterator_category; } | ||
| || derived_from<typename _It::iterator_category, output_iterator_tag>)) | ||
| requires (!_Has_iter_types<_It> && _Cpp17_iterator<_It> && !_Cpp17_input_iterator<_It>) | ||
| struct _Iterator_traits_base<_It> { | ||
CaseyCarter marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| using iterator_category = output_iterator_tag; | ||
| using value_type = void; | ||
| using difference_type = | ||
| typename _Iter_traits_difference<_Has_member_difference_type<incrementable_traits<_It>>>::template _Apply<_It>; | ||
| using value_type = void; | ||
| using pointer = void; | ||
| using reference = void; | ||
| }; | ||
|
|
@@ -619,8 +616,8 @@ template <class _It> | |
| requires (!_Has_iter_types<_It> && _Cpp17_input_iterator<_It>) | ||
| struct _Iterator_traits_base<_It> { | ||
| using iterator_category = typename _Iter_traits_category<_Has_member_iterator_category<_It>>::template _Apply<_It>; | ||
| using difference_type = typename incrementable_traits<_It>::difference_type; | ||
| using value_type = typename indirectly_readable_traits<_It>::value_type; | ||
| using difference_type = typename incrementable_traits<_It>::difference_type; | ||
| using pointer = typename _Iter_traits_pointer<( | ||
| _Has_member_pointer<_It> ? _Itraits_pointer_strategy::_Use_member | ||
| : _Has_member_arrow<_It&> ? _Itraits_pointer_strategy::_Use_decltype | ||
|
|
@@ -3551,24 +3548,36 @@ struct _Default_sentinel {}; // empty struct to serve as the end of a range | |
| #ifdef __cpp_lib_concepts | ||
| template <semiregular> | ||
| class move_sentinel; | ||
| #endif // __cpp_lib_concepts | ||
|
|
||
| template <class> | ||
| struct _Move_iterator_category {}; | ||
|
|
||
| // clang-format off | ||
| template <class _Iter> | ||
| class move_iterator { | ||
| public: | ||
| using iterator_type = _Iter; | ||
| #ifdef __cpp_lib_concepts | ||
| using iterator_concept = input_iterator_tag; | ||
| requires requires { typename _Iter_cat_t<_Iter>; } | ||
| struct _Move_iterator_category<_Iter> { | ||
| using iterator_category = conditional_t<derived_from<_Iter_cat_t<_Iter>, random_access_iterator_tag>, | ||
| random_access_iterator_tag, _Iter_cat_t<_Iter>>; | ||
| #else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv | ||
| }; | ||
| // clang-format on | ||
| #else // ^^^ Ranges / no Ranges vvv | ||
| template <class _Iter> | ||
| struct _Move_iterator_category { | ||
| using iterator_category = _Iter_cat_t<_Iter>; | ||
| }; | ||
| #endif // __cpp_lib_concepts | ||
|
|
||
| template <class _Iter> | ||
| class move_iterator : public _Move_iterator_category<_Iter> { | ||
| public: | ||
| using iterator_type = _Iter; | ||
| using value_type = _Iter_value_t<_Iter>; | ||
| using difference_type = _Iter_diff_t<_Iter>; | ||
| using pointer = _Iter; | ||
|
|
||
| #ifdef __cpp_lib_concepts | ||
| using reference = iter_rvalue_reference_t<_Iter>; | ||
| using iterator_concept = input_iterator_tag; | ||
| using reference = iter_rvalue_reference_t<_Iter>; | ||
| #else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv | ||
| using reference = | ||
| conditional_t<is_reference_v<_Iter_ref_t<_Iter>>, remove_reference_t<_Iter_ref_t<_Iter>>&&, _Iter_ref_t<_Iter>>; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note to reviewers: #1939 already implemented the |
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.