https://gcc.gnu.org/g:ea545f32c0e6cab75d0e9cb882485c35632b4e6b
commit r17-4778-gea545f32c0e6cab75d0e9cb882485c35632b4e6b Author: Tomasz KamiĆski <[email protected]> Date: Tue Sep 29 18:51:16 2026 +0200 libstdc++: Extract repeat_view::_Iterator to bits/ranges_util.h. This patch extracts repeat_view::_Iterator to stand-alone _Repeat_iterator declared in ranges_util.h. This allows it to be used to implement (size_t, const T&) overloads of container function (using it in hive), without including ranges header. As standard defines repeat_view::iterator(const T, index-type) as private, the corresponding _Repeat_iterator constructor is kept private, and std::__make_repeat_iterator is provided and used to construct it. Additionally, using _Repeat_iterator direclty, allows: * referencing to existing elements (repeat_view stores copy) * referencing to mutable elements (repeat_view yields const&) * using same specialization for unreachable_sentinel and ptrdiff_t bound. The bits/ranges_util.h is used instead of bits/stl_iterator.h, to avoid bringing dependency on __max_diff_type to that header. libstdc++-v3/ChangeLog: * include/bits/ranges_base.h (ranges::__detail::__to_signed_like): Moved from std/ranges. * include/bits/ranges_util.h (std::_Repeat_iterator) [__glibcxx_ranges]: Extracted from repeat_view::_Iterator. Apply remove_cv_t on value_type (as it is now const). Updated _S_difference_type to use __to_signed_like direclty. (std::__make_repeat_iterator): Define. * include/std/ranges (ranges::__detail::__to_signed_like): Move to bits/ranges_base.h (repeat_view::__index_type): Define. (repeat_view::_Iterator): Extracted to standalone _Repeat_iterator, and replaced with alias to it. (repeat_view::begin, repeat_view::end): Implement using std::__make_repeat_iterator. Reviewed-by: Jonathan Wakely <[email protected]> Diff: --- libstdc++-v3/include/bits/ranges_base.h | 19 ++++ libstdc++-v3/include/bits/ranges_util.h | 132 +++++++++++++++++++++++++++ libstdc++-v3/include/std/ranges | 157 ++------------------------------ 3 files changed, 157 insertions(+), 151 deletions(-) diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 2c2b44c1ac6c..7f4abbec3411 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -88,6 +88,25 @@ namespace ranges using __make_unsigned_like_t = decltype(__detail::__to_unsigned_like(std::declval<_Tp>())); + template<typename _Wp> + constexpr auto __to_signed_like(_Wp __w) noexcept + { + if constexpr (!integral<_Wp>) + return iter_difference_t<_Wp>(); + else if constexpr (sizeof(iter_difference_t<_Wp>) > sizeof(_Wp)) + return iter_difference_t<_Wp>(__w); + else if constexpr (sizeof(ptrdiff_t) > sizeof(_Wp)) + return ptrdiff_t(__w); + else if constexpr (sizeof(long long) > sizeof(_Wp)) + return (long long)(__w); +#ifdef __SIZEOF_INT128__ + else if constexpr (__SIZEOF_INT128__ > sizeof(_Wp)) + return __int128(__w); +#endif + else + return __max_diff_type(__w); + } + // Part of the constraints of ranges::borrowed_range template<typename _Tp> concept __maybe_borrowed_range diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 423767f00fcb..e6c02aa1d927 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -850,6 +850,138 @@ namespace ranges struct tuple_element<1, const ranges::subrange<_Iter, _Sent, _Kind>> { using type = _Sent; }; +template<typename _Tp, typename _IndexType> + class _Repeat_iterator; + + template<typename _Tp, typename _IndexType> + constexpr _Repeat_iterator<_Tp, _IndexType> + __make_repeat_iterator(_Tp&, _IndexType); + + template<typename _Tp, typename _IndexType> + class _Repeat_iterator + { + static auto + _S_difference_type() + { + if constexpr (__detail::__is_signed_integer_like<_IndexType>) + return _IndexType{}; + else + return ranges::__detail::__to_signed_like(_IndexType{}); + } + + _Tp* _M_value = nullptr; + _IndexType _M_current = _IndexType(); + + constexpr explicit + _Repeat_iterator(const _Tp* __value, _IndexType __bound = _IndexType()) + : _M_value(__value), _M_current(__bound) + { } + + public: + using iterator_concept = random_access_iterator_tag; + using iterator_category = random_access_iterator_tag; + using value_type = remove_cv_t<_Tp>; + using difference_type = decltype(_S_difference_type()); + + _Repeat_iterator() = default; + + constexpr _Tp& + operator*() const noexcept + { return *_M_value; } + + constexpr _Repeat_iterator& + operator++() + { + ++_M_current; + return *this; + } + + constexpr _Repeat_iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Repeat_iterator& + operator--() + { + __glibcxx_assert(_M_current > 0); + --_M_current; + return *this; + } + + constexpr _Repeat_iterator + operator--(int) + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Repeat_iterator& + operator+=(difference_type __n) + { + __glibcxx_assert(_M_current + __n >= 0); + _M_current += __n; + return *this; + } + + constexpr _Repeat_iterator& + operator-=(difference_type __n) + { + __glibcxx_assert(_M_current - __n >= 0); + _M_current -= __n; + return *this; + } + + constexpr _Tp& + operator[](difference_type __n) const noexcept + { return *(*this + __n); } + + friend constexpr bool + operator==(const _Repeat_iterator& __x, const _Repeat_iterator& __y) + { return __x._M_current == __y._M_current; } + + friend constexpr auto + operator<=>(const _Repeat_iterator& __x, const _Repeat_iterator& __y) + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Repeat_iterator + operator+(_Repeat_iterator __i, difference_type __n) + { + __i += __n; + return __i; + } + + friend constexpr _Repeat_iterator + operator+(difference_type __n, _Repeat_iterator __i) + { return __i + __n; } + + friend constexpr _Repeat_iterator + operator-(_Repeat_iterator __i, difference_type __n) + { + __i -= __n; + return __i; + } + + friend constexpr difference_type + operator-(const _Repeat_iterator& __x, const _Repeat_iterator& __y) + { + return (static_cast<difference_type>(__x._M_current) + - static_cast<difference_type>(__y._M_current)); + } + + friend constexpr _Repeat_iterator<_Tp, _IndexType> + __make_repeat_iterator<_Tp, _IndexType>(_Tp&, _IndexType); + }; + + template<typename _Tp, typename _IndexType> + constexpr _Repeat_iterator<_Tp, _IndexType> + __make_repeat_iterator(_Tp& __tp, _IndexType __bound) + { return _Repeat_iterator<_Tp, _IndexType>(std::addressof(__tp), __bound); } + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // library concepts diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index fe7c87b8f6ee..dde4ed90080d 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -502,25 +502,6 @@ namespace ranges namespace __detail { - template<typename _Wp> - constexpr auto __to_signed_like(_Wp __w) noexcept - { - if constexpr (!integral<_Wp>) - return iter_difference_t<_Wp>(); - else if constexpr (sizeof(iter_difference_t<_Wp>) > sizeof(_Wp)) - return iter_difference_t<_Wp>(__w); - else if constexpr (sizeof(ptrdiff_t) > sizeof(_Wp)) - return ptrdiff_t(__w); - else if constexpr (sizeof(long long) > sizeof(_Wp)) - return (long long)(__w); -#ifdef __SIZEOF_INT128__ - else if constexpr (__SIZEOF_INT128__ > sizeof(_Wp)) - return __int128(__w); -#endif - else - return __max_diff_type(__w); - } - template<typename _Wp> using __iota_diff_t = decltype(__to_signed_like(std::declval<_Wp>())); @@ -7981,11 +7962,13 @@ namespace views::__adaptor || same_as<_Bound, unreachable_sentinel_t>) class repeat_view : public view_interface<repeat_view<_Tp, _Bound>> { + using __index_type + = __conditional_t<same_as<_Bound, unreachable_sentinel_t>, ptrdiff_t, _Bound>; + using _Iterator = _Repeat_iterator<const _Tp, __index_type>; + [[no_unique_address]] __detail::__box<_Tp> _M_value; [[no_unique_address]] _Bound _M_bound = _Bound(); - class _Iterator; - template<typename _Range> friend constexpr auto views::__detail::__take_of_repeat_view(_Range&&, range_difference_t<_Range>); @@ -8030,11 +8013,11 @@ namespace views::__adaptor constexpr _Iterator begin() const - { return _Iterator(std::__addressof(*_M_value)); } + { return std::__make_repeat_iterator(*_M_value, __index_type(0)); } constexpr _Iterator end() const requires (!same_as<_Bound, unreachable_sentinel_t>) - { return _Iterator(std::__addressof(*_M_value), _M_bound); } + { return std::__make_repeat_iterator(*_M_value, _M_bound); } constexpr unreachable_sentinel_t end() const noexcept @@ -8050,134 +8033,6 @@ namespace views::__adaptor template<typename _Tp, typename _Bound = unreachable_sentinel_t> repeat_view(_Tp, _Bound = _Bound()) -> repeat_view<_Tp, _Bound>; - template<move_constructible _Tp, semiregular _Bound> - requires is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>> - && (__detail::__is_signed_integer_like<_Bound> - || (__detail::__is_integer_like<_Bound> && weakly_incrementable<_Bound>) - || same_as<_Bound, unreachable_sentinel_t>) - class repeat_view<_Tp, _Bound>::_Iterator - { - using __index_type - = __conditional_t<same_as<_Bound, unreachable_sentinel_t>, ptrdiff_t, _Bound>; - - static auto - _S_difference_type() - { - if constexpr (__detail::__is_signed_integer_like<__index_type>) - return __index_type{}; - else - return __detail::__iota_diff_t<__index_type>{}; - } - - const _Tp* _M_value = nullptr; - __index_type _M_current = __index_type(); - - constexpr explicit - _Iterator(const _Tp* __value, __index_type __bound = __index_type()) - : _M_value(__value), _M_current(__bound) - { } - - friend repeat_view; - - public: - using iterator_concept = random_access_iterator_tag; - using iterator_category = random_access_iterator_tag; - using value_type = _Tp; - using difference_type = decltype(_S_difference_type()); - - _Iterator() = default; - - constexpr const _Tp& - operator*() const noexcept - { return *_M_value; } - - constexpr _Iterator& - operator++() - { - ++_M_current; - return *this; - } - - constexpr _Iterator - operator++(int) - { - auto __tmp = *this; - ++*this; - return __tmp; - } - - constexpr _Iterator& - operator--() - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 4624. Inconsistent preconditions in repeat_view::iterator - __glibcxx_assert(_M_current > 0); - --_M_current; - return *this; - } - - constexpr _Iterator - operator--(int) - { - auto __tmp = *this; - --*this; - return __tmp; - } - - constexpr _Iterator& - operator+=(difference_type __n) - { - __glibcxx_assert(_M_current + __n >= 0); - _M_current += __n; - return *this; - } - - constexpr _Iterator& - operator-=(difference_type __n) - { - __glibcxx_assert(_M_current - __n >= 0); - _M_current -= __n; - return *this; - } - - constexpr const _Tp& - operator[](difference_type __n) const noexcept - { return *(*this + __n); } - - friend constexpr bool - operator==(const _Iterator& __x, const _Iterator& __y) - { return __x._M_current == __y._M_current; } - - friend constexpr auto - operator<=>(const _Iterator& __x, const _Iterator& __y) - { return __x._M_current <=> __y._M_current; } - - friend constexpr _Iterator - operator+(_Iterator __i, difference_type __n) - { - __i += __n; - return __i; - } - - friend constexpr _Iterator - operator+(difference_type __n, _Iterator __i) - { return __i + __n; } - - friend constexpr _Iterator - operator-(_Iterator __i, difference_type __n) - { - __i -= __n; - return __i; - } - - friend constexpr difference_type - operator-(const _Iterator& __x, const _Iterator& __y) - { - return (static_cast<difference_type>(__x._M_current) - - static_cast<difference_type>(__y._M_current)); - } - }; - namespace views { namespace __detail
