Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions stl/inc/iterator
Original file line number Diff line number Diff line change
Expand Up @@ -1016,15 +1016,20 @@ struct _Common_iterator_pointer_type<_Iter> {
using pointer = decltype(_STD declval<_Iter&>().operator->());
};

template <class _Iter>
concept _Has_forward_category = requires {
typename _Iter_cat_t<_Iter>;
requires derived_from<_Iter_cat_t<_Iter>, forward_iterator_tag>;
};

template <input_iterator _Iter, class _Se>
struct iterator_traits<common_iterator<_Iter, _Se>> {
using iterator_concept = conditional_t<forward_iterator<_Iter>, forward_iterator_tag, input_iterator_tag>;
using iterator_category =
conditional_t<derived_from<_Iter_cat_t<_Iter>, forward_iterator_tag>, forward_iterator_tag, input_iterator_tag>;
using value_type = iter_value_t<_Iter>;
using difference_type = iter_difference_t<_Iter>;
using pointer = typename _Common_iterator_pointer_type<_Iter>::pointer;
using reference = iter_reference_t<_Iter>;
using iterator_concept = conditional_t<forward_iterator<_Iter>, forward_iterator_tag, input_iterator_tag>;
using iterator_category = conditional_t<_Has_forward_category<_Iter>, forward_iterator_tag, input_iterator_tag>;
using value_type = iter_value_t<_Iter>;
using difference_type = iter_difference_t<_Iter>;
using pointer = typename _Common_iterator_pointer_type<_Iter>::pointer;
using reference = iter_reference_t<_Iter>;
};

template <class _Iter>
Expand Down
120 changes: 64 additions & 56 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -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};
Expand Down Expand Up @@ -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{};
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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{};

Expand Down Expand Up @@ -4002,18 +4008,20 @@ namespace ranges {
template <bool _Const>
class _Sentinel;

template <class _Traits> // TRANSITION, LWG-3289
template <class _Base>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to other reviewers: we already implement the equivalent of the split_view changes from P2259R1.

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;
Expand Down
39 changes: 24 additions & 15 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -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> {
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;
};
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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>>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to reviewers: #1939 already implemented the counted_iterator changes from P2259R1.

Expand Down
1 change: 0 additions & 1 deletion stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@
// P2106R0 Range Algorithm Result Types
// P2116R0 Removing tuple-Like Protocol Support From Fixed-Extent span
// P2259R1 Repairing Input Range Adaptors And counted_iterator
// (partially implemented)
// P2325R3 Views Should Not Be Required To Be Default Constructible
// P????R? directory_entry::clear_cache()

Expand Down
35 changes: 26 additions & 9 deletions tests/std/include/range_algorithm_support.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -592,19 +592,36 @@ namespace test {
}
};
// clang-format on

template <class Category, bool IsForward, bool IsProxy, bool EqAndCopy>
struct iterator_traits_base {};

template <class Category>
struct iterator_traits_base<Category, true, false, true> {
using iterator_category = Category;
};

template <class Category>
struct iterator_traits_base<Category, true, true, true> {
using iterator_category = input;
};

template <class Category, bool IsProxy>
struct iterator_traits_base<Category, false, IsProxy, true> {
using iterator_category = input;
};
} // namespace test

template <class Category, class Element, ::test::CanDifference Diff, ::test::CanCompare Eq, ::test::ProxyRef Proxy,
::test::IsWrapped Wrapped>
struct std::iterator_traits<::test::iterator<Category, Element, Diff, Eq, Proxy, Wrapped>> {
using iterator_concept = Category;
using iterator_category = conditional_t<derived_from<Category, forward_iterator_tag>, //
conditional_t<Proxy == ::test::ProxyRef::no, Category, input_iterator_tag>, //
conditional_t<static_cast<bool>(Eq), Category, void>>; // TRANSITION, LWG-3289
using value_type = remove_cv_t<Element>;
using difference_type = ptrdiff_t;
using pointer = conditional_t<derived_from<Category, contiguous_iterator_tag>, Element*, void>;
using reference = iter_reference_t<::test::iterator<Category, Element, Diff, Eq, Proxy, Wrapped>>;
struct std::iterator_traits<::test::iterator<Category, Element, Diff, Eq, Proxy, Wrapped>>
: ::test::iterator_traits_base<Category, derived_from<Category, forward_iterator_tag>,
Proxy == ::test::ProxyRef::yes, Eq == ::test::CanCompare::yes> {
using iterator_concept = Category;
using value_type = remove_cv_t<Element>;
using difference_type = ptrdiff_t;
using pointer = conditional_t<derived_from<Category, contiguous_iterator_tag>, Element*, void>;
using reference = iter_reference_t<::test::iterator<Category, Element, Diff, Eq, Proxy, Wrapped>>;
};

template <class Element, ::test::CanDifference Diff, ::test::IsWrapped Wrapped>
Expand Down
Loading