[PATCH] libstdc++: Handle integer-class types as bound of repeat_view
Tomasz Kamiński
tkaminsk@redhat.com
Fri Sep 18 11:22:11 GMT 2026
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".
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?
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
More information about the Libstdc++
mailing list