[libcxx-commits] [libcxx] [libc++][ranges] LWG3610: `iota_view::size` sometimes rejects integer-class types (PR #155169)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Jan 11 09:11:22 PST 2026
https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/155169
>From 16e553cd5ef275e8a6abf4445189dc4bb2a86715 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 24 Aug 2025 13:44:49 +0300
Subject: [PATCH 1/8] [libc++][ranges] LWG3610: iota_view::size sometimes
rejects integer-class types
Fixes #104948
- https://wg21.link/LWG3610
---
libcxx/include/__ranges/iota_view.h | 2 +-
.../range.iota.view/size.pass.cpp | 18 ++++++++++++++++++
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index 6b2576ec6b23d..29f96545ab34f 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -357,7 +357,7 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
requires(same_as<_Start, _BoundSentinel> && __advanceable<_Start>) ||
- (integral<_Start> && integral<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>
+ (__integer_like<_Start> && __integer_like<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>
{
if constexpr (__integer_like<_Start> && __integer_like<_BoundSentinel>) {
return (__value_ < 0)
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
index 8563b85f65dbd..bbfaf9c53b99f 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
@@ -16,8 +16,21 @@
#include <ranges>
#include "test_macros.h"
+#define TEST_HAS_NO_INT128
+#include "type_algorithms.h"
#include "types.h"
+template <typename T>
+concept HasSize = requires(const T t) { t.size(); };
+
+struct CheckForSize {
+ template <class T>
+ constexpr void operator()() {
+ static_assert(HasSize<std::ranges::iota_view<T, int>>);
+ static_assert(HasSize<std::ranges::iota_view<T, T>>);
+ }
+};
+
constexpr bool test() {
// Both are integer like and both are less than zero.
{
@@ -99,6 +112,11 @@ constexpr bool test() {
assert(sz == 10);
}
+ // LWG3610: `iota_view::size` sometimes rejects integer-class types
+ {
+ types::for_each(types::integer_types{}, CheckForSize{});
+ }
+
return true;
}
>From 00bb5a0e9b828657658a074c7d29e80094942632 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 25 Aug 2025 11:28:26 +0300
Subject: [PATCH 2/8] Updated test
---
.../ranges/range.factories/range.iota.view/size.pass.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
index bbfaf9c53b99f..b091d1c4f09f8 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
@@ -24,10 +24,11 @@ template <typename T>
concept HasSize = requires(const T t) { t.size(); };
struct CheckForSize {
- template <class T>
+ template <class IntegerLikeT>
constexpr void operator()() {
- static_assert(HasSize<std::ranges::iota_view<T, int>>);
- static_assert(HasSize<std::ranges::iota_view<T, T>>);
+ types::for_each(types::integer_types{}, []<typename BoundT>() {
+ static_assert(HasSize<std::ranges::iota_view<IntegerLikeT, BoundT>>);
+ });
}
};
>From b339e813b14a41378ddd21790cc58c498b0583b6 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 25 Aug 2025 14:26:11 +0300
Subject: [PATCH 3/8] Added `__int128_t` support
---
.../ranges/range.factories/range.iota.view/begin.pass.cpp | 4 ++++
.../ranges/range.factories/range.iota.view/end.pass.cpp | 8 ++++++++
.../range.iota.view/iterator/star.pass.cpp | 6 ++++++
.../range.iota.view/iterator/subscript.pass.cpp | 6 ++++++
.../ranges/range.factories/range.iota.view/size.pass.cpp | 1 -
5 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp
index 06419c1b14ee0..dbe052ea18287 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp
@@ -40,6 +40,10 @@ constexpr void testType() {
constexpr bool test() {
testType<SomeInt>();
+#ifndef TEST_HAS_NO_INT128
+ testType<__int128_t>();
+ testType<__uint128_t>();
+#endif
testType<long long>();
testType<unsigned long long>();
testType<signed long>();
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp
index 6abbef55b6ba7..d12079fdb5eec 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp
@@ -61,6 +61,14 @@ constexpr void testType(U u) {
constexpr bool test() {
testType<SomeInt>(SomeInt(10));
testType<SomeInt>(IntComparableWith(SomeInt(10)));
+#ifndef TEST_HAS_NO_INT128
+ testType<__int128_t>(__int128_t(10));
+ testType<__uint128_t>(__uint128_t(10));
+#endif
+ testType<signed long long>(10LL);
+ testType<unsigned long long>(10ULL);
+ testType<signed long long>(IntComparableWith<signed long long>(10));
+ testType<unsigned long long>(IntComparableWith<unsigned long long>(10));
testType<signed long>(IntComparableWith<signed long>(10));
testType<unsigned long>(IntComparableWith<unsigned long>(10));
testType<int>(IntComparableWith<int>(10));
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp
index 570c74e29c686..b776d90c5e5e3 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp
@@ -81,6 +81,12 @@ constexpr void testType() {
constexpr bool test() {
testType<SomeInt>();
testType<NotNoexceptCopy>();
+#ifndef TEST_HAS_NO_INT128
+ testType<__int128_t>();
+ testType<__uint128_t>();
+#endif
+ testType<signed long long>();
+ testType<unsigned long long>();
testType<signed long>();
testType<unsigned long>();
testType<int>();
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp
index 0e5aca0dd554c..786b63dfeedee 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp
@@ -47,6 +47,12 @@ constexpr void testType() {
constexpr bool test() {
testType<SomeInt>();
+#ifndef TEST_HAS_NO_INT128
+ testType<__int128_t>();
+ testType<__uint128_t>();
+#endif
+ testType<signed long long>();
+ testType<unsigned long long>();
testType<signed long>();
testType<unsigned long>();
testType<int>();
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
index b091d1c4f09f8..79f9d1d2bab5f 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
@@ -16,7 +16,6 @@
#include <ranges>
#include "test_macros.h"
-#define TEST_HAS_NO_INT128
#include "type_algorithms.h"
#include "types.h"
>From 66908eec6325b014741e9e1ec5abd8f36973cc58 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 20 Nov 2025 05:15:33 +0200
Subject: [PATCH 4/8] Revert changes
---
libcxx/include/__ranges/iota_view.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index 29f96545ab34f..6b2576ec6b23d 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -357,7 +357,7 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
requires(same_as<_Start, _BoundSentinel> && __advanceable<_Start>) ||
- (__integer_like<_Start> && __integer_like<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>
+ (integral<_Start> && integral<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>
{
if constexpr (__integer_like<_Start> && __integer_like<_BoundSentinel>) {
return (__value_ < 0)
>From 20c348625ec58f9f8426e6c5adfa7f94dbb525e4 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 20 Nov 2025 05:29:00 +0200
Subject: [PATCH 5/8] Reverted too mucb
---
libcxx/include/__ranges/iota_view.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index 6b2576ec6b23d..29f96545ab34f 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -357,7 +357,7 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
requires(same_as<_Start, _BoundSentinel> && __advanceable<_Start>) ||
- (integral<_Start> && integral<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>
+ (__integer_like<_Start> && __integer_like<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>
{
if constexpr (__integer_like<_Start> && __integer_like<_BoundSentinel>) {
return (__value_ < 0)
>From 59d626c74f58436114fa0be1a319852e150dbc21 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 20 Nov 2025 05:40:37 +0200
Subject: [PATCH 6/8] Cleanup
---
.../range.factories/range.iota.view/size.pass.cpp | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
index 79f9d1d2bab5f..2b20e010fa2f5 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
@@ -22,15 +22,6 @@
template <typename T>
concept HasSize = requires(const T t) { t.size(); };
-struct CheckForSize {
- template <class IntegerLikeT>
- constexpr void operator()() {
- types::for_each(types::integer_types{}, []<typename BoundT>() {
- static_assert(HasSize<std::ranges::iota_view<IntegerLikeT, BoundT>>);
- });
- }
-};
-
constexpr bool test() {
// Both are integer like and both are less than zero.
{
@@ -114,7 +105,11 @@ constexpr bool test() {
// LWG3610: `iota_view::size` sometimes rejects integer-class types
{
- types::for_each(types::integer_types{}, CheckForSize{});
+ types::for_each(types::integer_types{}, []<typename IntegerLikeT>() {
+ types::for_each(types::integer_types{}, []<typename BoundT>() {
+ static_assert(HasSize<std::ranges::iota_view<IntegerLikeT, BoundT>>);
+ });
+ });
}
return true;
>From be0ed92d3cdc944bf997cf34714a9d666a4ddd35 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 11 Jan 2026 19:03:23 +0200
Subject: [PATCH 7/8] Revert `int128_t` support in tests
---
.../ranges/range.factories/range.iota.view/begin.pass.cpp | 4 ----
.../ranges/range.factories/range.iota.view/end.pass.cpp | 8 --------
.../range.iota.view/iterator/star.pass.cpp | 6 ------
.../range.iota.view/iterator/subscript.pass.cpp | 6 ------
.../ranges/range.factories/range.iota.view/size.pass.cpp | 1 +
5 files changed, 1 insertion(+), 24 deletions(-)
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp
index dbe052ea18287..06419c1b14ee0 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/begin.pass.cpp
@@ -40,10 +40,6 @@ constexpr void testType() {
constexpr bool test() {
testType<SomeInt>();
-#ifndef TEST_HAS_NO_INT128
- testType<__int128_t>();
- testType<__uint128_t>();
-#endif
testType<long long>();
testType<unsigned long long>();
testType<signed long>();
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp
index d12079fdb5eec..6abbef55b6ba7 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/end.pass.cpp
@@ -61,14 +61,6 @@ constexpr void testType(U u) {
constexpr bool test() {
testType<SomeInt>(SomeInt(10));
testType<SomeInt>(IntComparableWith(SomeInt(10)));
-#ifndef TEST_HAS_NO_INT128
- testType<__int128_t>(__int128_t(10));
- testType<__uint128_t>(__uint128_t(10));
-#endif
- testType<signed long long>(10LL);
- testType<unsigned long long>(10ULL);
- testType<signed long long>(IntComparableWith<signed long long>(10));
- testType<unsigned long long>(IntComparableWith<unsigned long long>(10));
testType<signed long>(IntComparableWith<signed long>(10));
testType<unsigned long>(IntComparableWith<unsigned long>(10));
testType<int>(IntComparableWith<int>(10));
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp
index b776d90c5e5e3..570c74e29c686 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/star.pass.cpp
@@ -81,12 +81,6 @@ constexpr void testType() {
constexpr bool test() {
testType<SomeInt>();
testType<NotNoexceptCopy>();
-#ifndef TEST_HAS_NO_INT128
- testType<__int128_t>();
- testType<__uint128_t>();
-#endif
- testType<signed long long>();
- testType<unsigned long long>();
testType<signed long>();
testType<unsigned long>();
testType<int>();
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp
index 786b63dfeedee..0e5aca0dd554c 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/subscript.pass.cpp
@@ -47,12 +47,6 @@ constexpr void testType() {
constexpr bool test() {
testType<SomeInt>();
-#ifndef TEST_HAS_NO_INT128
- testType<__int128_t>();
- testType<__uint128_t>();
-#endif
- testType<signed long long>();
- testType<unsigned long long>();
testType<signed long>();
testType<unsigned long>();
testType<int>();
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
index 2b20e010fa2f5..f61ead5c1cbb3 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
@@ -17,6 +17,7 @@
#include "test_macros.h"
#include "type_algorithms.h"
+
#include "types.h"
template <typename T>
>From eeb8db293a32f7d1cad81317b396530db5857ea2 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 11 Jan 2026 19:10:52 +0200
Subject: [PATCH 8/8] Fix doc
---
libcxx/docs/Status/Cxx23Issues.csv | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv
index cc83a7da9c25e..3bb079da09f8b 100644
--- a/libcxx/docs/Status/Cxx23Issues.csv
+++ b/libcxx/docs/Status/Cxx23Issues.csv
@@ -143,7 +143,7 @@
"`LWG3598 <https://wg21.link/LWG3598>`__","``system_category().default_error_condition(0)`` is underspecified","2022-02 (Virtual)","","","`#104945 <https://github.com/llvm/llvm-project/issues/104945>`__",""
"`LWG3601 <https://wg21.link/LWG3601>`__","common_iterator's postfix-proxy needs ``indirectly_readable`` ","2022-02 (Virtual)","","","`#104946 <https://github.com/llvm/llvm-project/issues/104946>`__",""
"`LWG3607 <https://wg21.link/LWG3607>`__","``contiguous_iterator`` should not be allowed to have custom ``iter_move`` and ``iter_swap`` behavior","2022-02 (Virtual)","|Nothing To Do|","","`#104947 <https://github.com/llvm/llvm-project/issues/104947>`__",""
-"`LWG3610 <https://wg21.link/LWG3610>`__","``iota_view::size`` sometimes rejects integer-class types","2022-02 (Virtual)","","","`#104948 <https://github.com/llvm/llvm-project/issues/104948>`__",""
+"`LWG3610 <https://wg21.link/LWG3610>`__","``iota_view::size`` sometimes rejects integer-class types","2022-02 (Virtual)","|Complete|","22","`#104948 <https://github.com/llvm/llvm-project/issues/104948>`__",""
"`LWG3612 <https://wg21.link/LWG3612>`__","Inconsistent pointer alignment in ``std::format`` ","2022-02 (Virtual)","|Complete|","14","`#104949 <https://github.com/llvm/llvm-project/issues/104949>`__",""
"`LWG3616 <https://wg21.link/LWG3616>`__","LWG 3498 seems to miss the non-member ``swap`` for ``basic_syncbuf`` ","2022-02 (Virtual)","|Complete|","18","`#104950 <https://github.com/llvm/llvm-project/issues/104950>`__",""
"`LWG3618 <https://wg21.link/LWG3618>`__","Unnecessary ``iter_move`` for ``transform_view::iterator`` ","2022-02 (Virtual)","|Complete|","19","`#104951 <https://github.com/llvm/llvm-project/issues/104951>`__",""
More information about the libcxx-commits
mailing list