diff --git a/stl/inc/iterator b/stl/inc/iterator index 08814af493b..487af063f5b 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -1038,10 +1038,35 @@ struct iterator_traits> { }; // CLASS TEMPLATE counted_iterator +template +struct _Counted_iterator_value_type_base {}; + +template +struct _Counted_iterator_value_type_base<_Iter> { + using value_type = iter_value_t<_Iter>; +}; + +template +struct _Counted_iterator_category_base : _Counted_iterator_value_type_base<_Iter> {}; + +template <_Has_member_iterator_category _Iter> +struct _Counted_iterator_category_base<_Iter> : _Counted_iterator_value_type_base<_Iter> { + using iterator_category = typename _Iter::iterator_category; +}; + +template +struct _Counted_iterator_concept_base : _Counted_iterator_category_base<_Iter> {}; + +template <_Has_member_iterator_concept _Iter> +struct _Counted_iterator_concept_base<_Iter> : _Counted_iterator_category_base<_Iter> { + using iterator_concept = typename _Iter::iterator_concept; +}; + template -class counted_iterator { +class counted_iterator : public _Counted_iterator_concept_base<_Iter> { public: - using iterator_type = _Iter; + using iterator_type = _Iter; + using difference_type = iter_difference_t<_Iter>; // [counted.iter.const] constexpr counted_iterator() requires default_initializable<_Iter> = default; @@ -1099,6 +1124,10 @@ public: return *_Current; } + _NODISCARD constexpr auto operator->() const noexcept requires contiguous_iterator<_Iter> { + return _STD to_address(_Current); + } + _NODISCARD constexpr decltype(auto) operator[](const iter_difference_t<_Iter> _Diff) const requires random_access_iterator<_Iter> { #if _ITERATOR_DEBUG_LEVEL != 0 @@ -1323,25 +1352,12 @@ private: iter_difference_t<_Iter> _Length = 0; }; -template -struct incrementable_traits> { - using difference_type = iter_difference_t<_Iter>; -}; - +// clang-format off template + requires (!_Is_from_primary>) struct iterator_traits> : iterator_traits<_Iter> { - using pointer = void; -}; - -template -struct pointer_traits> { // TRANSITION, address LWG-3408 and include this - using pointer = counted_iterator<_Iter>; - using element_type = remove_reference_t>; - using difference_type = iter_difference_t<_Iter>; - - _NODISCARD static constexpr element_type* to_address(const pointer _It) noexcept { - return _STD to_address(_It.base()); - } + // clang-format on + using pointer = conditional_t, add_pointer_t>, void>; }; #endif // __cpp_lib_concepts diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index af5917c8526..35f5e22299a 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -245,6 +245,8 @@ // P2102R0 Making "Implicit Expression Variations" More Explicit // 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() diff --git a/tests/std/tests/P0896R4_common_iterator/test.cpp b/tests/std/tests/P0896R4_common_iterator/test.cpp index 317118c1144..1c7b93b40ad 100644 --- a/tests/std/tests/P0896R4_common_iterator/test.cpp +++ b/tests/std/tests/P0896R4_common_iterator/test.cpp @@ -189,7 +189,7 @@ bool test_operator_arrow() { assert(*countedIter == P(0, 1)); assert(countedIter->first == 0); assert(countedIter->second == 1); - static_assert(is_same_v()), P*>); + static_assert(is_same_v()), counted_iterator const&>); return true; } diff --git a/tests/std/tests/P0896R4_counted_iterator/test.cpp b/tests/std/tests/P0896R4_counted_iterator/test.cpp index e35b4fcacf0..715d5a99d53 100644 --- a/tests/std/tests/P0896R4_counted_iterator/test.cpp +++ b/tests/std/tests/P0896R4_counted_iterator/test.cpp @@ -305,6 +305,43 @@ struct instantiator { } }; +// Also test P2259R1 Repairing input range adaptors and counted_iterator +struct simple_forward_iter { + using value_type = double; + using difference_type = long; + using iterator_category = input_iterator_tag; + using iterator_concept = forward_iterator_tag; + + value_type operator*() const; + simple_forward_iter& operator++(); + simple_forward_iter operator++(int); + + bool operator==(const simple_forward_iter&) const; +}; + +using CI = counted_iterator; + +static_assert(same_as::iterator_category, input_iterator_tag>); +static_assert(forward_iterator); +static_assert(forward_iterator); +static_assert(!contiguous_iterator); +static_assert(same_as); +static_assert(same_as); +static_assert(same_as); +static_assert(same_as); + +void test_P2259() { + struct A { + int m; + }; + A a[2] = {{1}, {2}}; + counted_iterator ci{a, 2}; + reverse_iterator ri{ci + 1}; + static_assert(contiguous_iterator); + assert(ci->m == 1); + assert(ri->m == 1); +} + int main() { STATIC_ASSERT((with_writable_iterators::call(), true)); with_writable_iterators::call(); @@ -317,4 +354,6 @@ int main() { _Seek_wrapped(ci, uci); assert((ci == counted_iterator{ranges::next(lst.begin()), 1})); } + + test_P2259(); }