On Fri, 18 Sep 2026 at 13:22 +0200, Tomasz KamiƄski wrote:
As iter_difference_t is not defined for integer-class types, the
unsigned integer-class types are rejected (they are not
weekly_incrementable) and difference_type definition is updated to
not instantiate __iota_diff_t for all signed integer-like types.

This implements LWG4581, "constant_of(^^v) for variable v of reference
to array/function type produces reflection of pointer constant".

Wrong LWG number and title.


The standard uses integer-like-with-usable-difference-type helper
concept, but I do not think it provides enough improvement to justify
adding a namespace level symbol.

libstdc++-v3/ChangeLog:

        * include/std/ranges (std::repeat_view, repeat_view::_Iterator):
        Update constrains.
        (repeat_view::_Iterator::_S_difference_type): Define.
        (repeat_view::_Iterator::difference_type): Define in terms of
        _S_difference_type.
        * testsuite/std/ranges/repeat/1.cc: New test case.
---
It took me some time to reffer unsigned integer-class, without using
to std::__detail::__max_size_type directly.

Tested on x86_64-linux. *repeat* test also passed in all standard modes,
debug, assertions, -m32. OK for trunk?

OK with the changelog fixed to refer to LWG 3875

libstdc++-v3/include/std/ranges               | 21 +++++++---
libstdc++-v3/testsuite/std/ranges/repeat/1.cc | 42 +++++++++++++++++++
2 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index a7fb2312fe8..1c0991cae13 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -7976,7 +7976,9 @@ namespace views::__adaptor
#ifdef __cpp_lib_ranges_repeat // C++ >= 23
  template<move_constructible _Tp, semiregular _Bound = unreachable_sentinel_t>
    requires is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>>
-      && (__detail::__is_integer_like<_Bound> || same_as<_Bound, 
unreachable_sentinel_t>)
+      && (__detail::__is_signed_integer_like<_Bound>
+         || (__detail::__is_integer_like<_Bound> && 
weakly_incrementable<_Bound>)
+         || same_as<_Bound, unreachable_sentinel_t>)
  class repeat_view : public view_interface<repeat_view<_Tp, _Bound>>
  {
    [[no_unique_address]] __detail::__box<_Tp> _M_value;
@@ -8050,12 +8052,23 @@ namespace views::__adaptor

  template<move_constructible _Tp, semiregular _Bound>
    requires is_object_v<_Tp> && same_as<_Tp, remove_cv_t<_Tp>>
-      && (__detail::__is_integer_like<_Bound> || same_as<_Bound, 
unreachable_sentinel_t>)
+      && (__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();

@@ -8073,9 +8086,7 @@ namespace views::__adaptor
    using iterator_concept = random_access_iterator_tag;
    using iterator_category = random_access_iterator_tag;
    using value_type = _Tp;
-    using difference_type = 
__conditional_t<__detail::__is_signed_integer_like<__index_type>,
-                                           __index_type,
-                                           
__detail::__iota_diff_t<__index_type>>;
+    using difference_type = decltype(_S_difference_type());

    _Iterator() = default;

diff --git a/libstdc++-v3/testsuite/std/ranges/repeat/1.cc 
b/libstdc++-v3/testsuite/std/ranges/repeat/1.cc
index eb0c848e9ce..3b81e528310 100644
--- a/libstdc++-v3/testsuite/std/ranges/repeat/1.cc
+++ b/libstdc++-v3/testsuite/std/ranges/repeat/1.cc
@@ -172,6 +172,47 @@ test09()
  VERIFY( v[0][0] == 5 );
}

+template<typename T, typename B>
+concept can_repeat = requires (T t, B b) {
+  typename ranges::repeat_view<T, B>;
+  views::repeat(t, b);
+};
+
+void
+test10()
+{
+  // LWG 3875. std::ranges::repeat_view<T, IntegerClass>::iterator may be 
ill-formed
+#ifdef __SIZEOF_INT128__
+  using max_sint = __int128;
+  using max_uint = unsigned __int128;
+#else
+  using max_sint = long long;
+  using max_uint = unsigned long long;
+#endif
+
+  static_assert( can_repeat<int, max_sint> );
+  ranges::repeat_view<int, max_sint> r1(1, 10);
+  VERIFY( ranges::count(r1, 1) == 10 );
+
+  static_assert( can_repeat<int, max_uint> );
+  ranges::repeat_view<int, max_uint> r2(2, 11);
+  VERIFY( ranges::count(r2, 2) == 11 );
+
+  using iotav = ranges::iota_view<max_sint, max_sint>;
+  using sint_class = ranges::range_difference_t<iotav>;
+  static_assert( !std::is_integral_v<sint_class> );
+
+  static_assert( can_repeat<int, sint_class> );
+  ranges::repeat_view<int, sint_class> r3(3, 12);
+  VERIFY( ranges::count(r3, 3) == 12 );
+
+  using iotas = ranges::subrange<ranges::iterator_t<iotav>>;
+  using uint_class = ranges::range_size_t<iotas>;
+  static_assert( !std::is_integral_v<uint_class> );
+
+  static_assert( !can_repeat<int, uint_class> );
+}
+
int
main()
{
@@ -184,4 +225,5 @@ main()
  test07();
  test08();
  test09();
+  test10();
}
--
2.55.0



Reply via email to