[PATCH] libstdc++: Extract repeat_view::_Iterator to bits/ranges_util.h.
Tomasz Kamiński
tkaminsk@redhat.com
Tue Sep 29 06:56:19 GMT 2026
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.
---
This also includes implementation of LWG4624, that I have posted separately
https://gcc.gnu.org/pipermail/libstdc++/2026-September/067846.html.
Should I create an ranges_iterator.h file in this commit, or do it as
separate?
Tested on powerpc64 anx 86_64 linux. OK for trunk?
libstdc++-v3/include/bits/ranges_base.h | 19 +++
libstdc++-v3/include/bits/ranges_util.h | 132 +++++++++++++++++++
libstdc++-v3/include/bits/stl_iterator.h | 2 +
libstdc++-v3/include/std/ranges | 157 +----------------------
4 files changed, 159 insertions(+), 151 deletions(-)
diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h
index 2c2b44c1ac6..7f4abbec341 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 423767f00fc..e6c02aa1d92 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/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index bcc22c50de5..ec008022b9b 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -3011,7 +3011,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
make_const_sentinel(_Sent __s)
noexcept(is_nothrow_convertible_v<_Sent, const_sentinel<_Sent>>)
{ return __s; }
+
#endif // C++23 ranges_as_const
+
#endif // C++20 ranges
/// @} group iterators
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index fe7c87b8f6e..dde4ed90080 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
--
2.55.0
More information about the Libstdc++
mailing list