[libcxx-commits] [libcxx] [libc++][ranges] P3060R3: Add `std::views::indices(n)` (PR #146823)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jul 22 10:08:37 PDT 2025
https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/146823
>From 51d2b416c9da4f5edf1e9270d70287e572a92335 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 3 Jul 2025 07:54:53 +0300
Subject: [PATCH 01/12] [libc++][ranges] P3060R3: Add `std::views::indices(n)`
Implements: P3060R3
# References
- https://github.com/cplusplus/draft/issues/7966
- https://github.com/cplusplus/draft/pull/8006
- https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3060r2.html
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__ranges/indices_view.h | 49 ++++++++++++++++++++++++++
libcxx/include/module.modulemap.in | 1 +
libcxx/include/ranges | 4 +++
4 files changed, 55 insertions(+)
create mode 100644 libcxx/include/__ranges/indices_view.h
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index cd6583cb62c24..fdd5c2f5e2a3b 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -713,6 +713,7 @@ set(files
__ranges/enable_view.h
__ranges/filter_view.h
__ranges/from_range.h
+ __ranges/indices_view.h
__ranges/iota_view.h
__ranges/istream_view.h
__ranges/join_view.h
diff --git a/libcxx/include/__ranges/indices_view.h b/libcxx/include/__ranges/indices_view.h
new file mode 100644
index 0000000000000..ea3a98e94696b
--- /dev/null
+++ b/libcxx/include/__ranges/indices_view.h
@@ -0,0 +1,49 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___RANGES_INDECES_VIEW_H
+#define _LIBCPP___RANGES_INDECES_VIEW_H
+
+#include <__assert>
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__ranges/iota_view.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+namespace ranges {
+
+namespace views {
+
+inline constexpr auto indices = [](__integer_like auto __size) {
+ return ranges::views::iota(decletype(__size), __size);
+};
+
+inline namespace __cpo {
+
+} // namespace __cpo
+} // namespace views
+} // namespace ranges
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_INDECES_VIEW_H
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index ac497208bdce4..a69a7245eb699 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1887,6 +1887,7 @@ module std [system] {
export std.functional.bind_back
}
module from_range { header "__ranges/from_range.h" }
+ module indices_view { header "__ranges/indices_view.h" }
module iota_view { header "__ranges/iota_view.h" }
module istream_view { header "__ranges/istream_view.h" }
module join_view { header "__ranges/join_view.h" }
diff --git a/libcxx/include/ranges b/libcxx/include/ranges
index 96d7a6b897188..f4b7a8a70f43e 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -453,6 +453,10 @@ namespace std {
# include <__ranges/zip_view.h>
# endif
+# if _LIBCPP_STD_VER >= 26
+# include <__ranges/indeces_view.h>
+# endif
+
# include <version>
// standard-mandated includes
>From 97e9af8efc58004fc3897974258125526050d0a2 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 3 Jul 2025 09:31:14 +0300
Subject: [PATCH 02/12] Implement and cleanup
---
libcxx/include/CMakeLists.txt | 1 -
libcxx/include/__ranges/indices_view.h | 49 -----
libcxx/include/__ranges/iota_view.h | 11 +
libcxx/include/module.modulemap.in | 1 -
libcxx/include/ranges | 4 -
.../range.iota.view/indices.pass.cpp | 199 ++++++++++++++++++
6 files changed, 210 insertions(+), 55 deletions(-)
delete mode 100644 libcxx/include/__ranges/indices_view.h
create mode 100644 libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index fdd5c2f5e2a3b..cd6583cb62c24 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -713,7 +713,6 @@ set(files
__ranges/enable_view.h
__ranges/filter_view.h
__ranges/from_range.h
- __ranges/indices_view.h
__ranges/iota_view.h
__ranges/istream_view.h
__ranges/join_view.h
diff --git a/libcxx/include/__ranges/indices_view.h b/libcxx/include/__ranges/indices_view.h
deleted file mode 100644
index ea3a98e94696b..0000000000000
--- a/libcxx/include/__ranges/indices_view.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP___RANGES_INDECES_VIEW_H
-#define _LIBCPP___RANGES_INDECES_VIEW_H
-
-#include <__assert>
-#include <__config>
-#include <__iterator/concepts.h>
-#include <__ranges/iota_view.h>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-# pragma GCC system_header
-#endif
-
-_LIBCPP_PUSH_MACROS
-#include <__undef_macros>
-
-_LIBCPP_BEGIN_NAMESPACE_STD
-
-#if _LIBCPP_STD_VER >= 26
-
-namespace ranges {
-
-namespace views {
-
-inline constexpr auto indices = [](__integer_like auto __size) {
- return ranges::views::iota(decletype(__size), __size);
-};
-
-inline namespace __cpo {
-
-} // namespace __cpo
-} // namespace views
-} // namespace ranges
-
-#endif // _LIBCPP_STD_VER >= 26
-
-_LIBCPP_END_NAMESPACE_STD
-
-_LIBCPP_POP_MACROS
-
-#endif // _LIBCPP___RANGES_INDECES_VIEW_H
diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index 4b84585258b91..732a501c07857 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -371,6 +371,7 @@ template <class _Start, class _BoundSentinel>
inline constexpr bool enable_borrowed_range<iota_view<_Start, _BoundSentinel>> = true;
namespace views {
+
namespace __iota {
struct __fn {
template <class _Start>
@@ -392,6 +393,16 @@ struct __fn {
inline namespace __cpo {
inline constexpr auto iota = __iota::__fn{};
} // namespace __cpo
+
+
+# if _LIBCPP_STD_VER >= 26
+
+inline constexpr auto indices = [](__integer_like auto __size) {
+ return ranges::views::iota(decltype(__size){}, __size);
+};
+
+# endif
+
} // namespace views
} // namespace ranges
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index a69a7245eb699..ac497208bdce4 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1887,7 +1887,6 @@ module std [system] {
export std.functional.bind_back
}
module from_range { header "__ranges/from_range.h" }
- module indices_view { header "__ranges/indices_view.h" }
module iota_view { header "__ranges/iota_view.h" }
module istream_view { header "__ranges/istream_view.h" }
module join_view { header "__ranges/join_view.h" }
diff --git a/libcxx/include/ranges b/libcxx/include/ranges
index f4b7a8a70f43e..96d7a6b897188 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -453,10 +453,6 @@ namespace std {
# include <__ranges/zip_view.h>
# endif
-# if _LIBCPP_STD_VER >= 26
-# include <__ranges/indeces_view.h>
-# endif
-
# include <version>
// standard-mandated includes
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
new file mode 100644
index 0000000000000..01806c27a896f
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
@@ -0,0 +1,199 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+#include <cassert>
+#include <cstddef>
+#include <ranges>
+#include <vector>
+
+#include "test_macros.h"
+#define TEST_HAS_NO_INT128 // Size cannot be larger than 64 bits
+#include "type_algorithms.h"
+
+#include "types.h"
+
+// #include <compare>
+
+// class IntegerLike {
+// int value;
+
+// public:
+// // Constructor
+// IntegerLike(int v = 0) : value(v) {}
+
+// // Conversion to int
+// operator int() const { return value; }
+
+// // Conversion to std::size_t
+// // This is necessary for std::ranges::views::indices to work with IntegerLike
+// operator std::size_t() const { return static_cast<std::size_t>(value); }
+
+// // Equality and comparison
+// auto operator<=>(const IntegerLike&) const = default;
+
+// // Arithmetic
+// IntegerLike operator+(const IntegerLike& other) const { return IntegerLike(value + other.value); }
+
+// IntegerLike operator-(const IntegerLike& other) const { return IntegerLike(value - other.value); }
+
+// IntegerLike operator*(const IntegerLike& other) const { return IntegerLike(value * other.value); }
+
+// IntegerLike operator/(const IntegerLike& other) const { return IntegerLike(value / other.value); }
+
+// // Compound assignment
+// IntegerLike& operator+=(const IntegerLike& other) {
+// value += other.value;
+// return *this;
+// }
+
+// IntegerLike& operator-=(const IntegerLike& other) {
+// value -= other.value;
+// return *this;
+// }
+
+// IntegerLike& operator*=(const IntegerLike& other) {
+// value *= other.value;
+// return *this;
+// }
+
+// IntegerLike& operator/=(const IntegerLike& other) {
+// value /= other.value;
+// return *this;
+// }
+
+// // Increment / Decrement
+// IntegerLike& operator++() {
+// ++value;
+// return *this;
+// }
+
+// IntegerLike operator++(int) {
+// IntegerLike tmp = *this;
+// ++(*this);
+// return tmp;
+// }
+
+// IntegerLike& operator--() {
+// --value;
+// return *this;
+// }
+
+// IntegerLike operator--(int) {
+// IntegerLike tmp = *this;
+// --(*this);
+// return tmp;
+// }
+// };
+
+// Test SFINAE.
+
+template <typename SizeType>
+concept HasIndices = requires(SizeType s) { std::ranges::views::indices(s); };
+
+struct NotIntegerLike {};
+
+struct IntegerTypesTest {
+ template <class T>
+ constexpr void operator()() {
+ static_assert(HasIndices<T>);
+ }
+};
+
+void test_SFIANE() {
+ static_assert(HasIndices<std::size_t>);
+ types::for_each(types::integer_types(), IntegerTypesTest{});
+
+ static_assert(!HasIndices<bool>);
+ static_assert(!HasIndices<float>);
+ static_assert(!HasIndices<void>);
+ static_assert(!HasIndices<SomeInt>); // Does satisfy is_integer_like, but not the conversion to std::size_t
+ static_assert(!HasIndices<NotIntegerLike>);
+}
+
+constexpr bool test() {
+ {
+ // Check that the indices view works as expected
+ auto indices_view = std::ranges::views::indices(5);
+ assert(indices_view.size() == 5);
+
+ // This should be valid, as indices_view is a range of integers
+ assert(indices_view[0] == 0);
+ assert(indices_view[1] == 1);
+ assert(indices_view[2] == 2);
+ assert(indices_view[3] == 3);
+ assert(indices_view[4] == 4);
+
+ // Check that the view is a range
+ static_assert(std::ranges::range<decltype(indices_view)>);
+ }
+
+ // {
+ // // Check that the indices view works as expected
+ // auto indices_view = std::ranges::views::indices(IntegerLike{5});
+ // assert(indices_view.size() == 5);
+
+ // // Check that the view is a range
+ // static_assert(std::ranges::range<decltype(indices_view)>);
+
+ // // This should be valid, as indices_view is a range of integers
+ // assert(indices_view[0] == 0);
+ // assert(indices_view[1] == 1);
+ // assert(indices_view[2] == 2);
+ // assert(indices_view[3] == 3);
+ // assert(indices_view[4] == 4);
+ // }
+
+ {
+ std::vector v(5, 0);
+
+ // Check that the indices view works as expected
+ auto indices_view = std::ranges::views::indices(std::ranges::size(v));
+ assert(indices_view.size() == 5);
+
+ // Check that the view is a range
+ static_assert(std::ranges::range<decltype(indices_view)>);
+
+ // This should be valid, as indices_view is a range of integers
+ assert(indices_view[0] == 0);
+ assert(indices_view[1] == 1);
+ assert(indices_view[2] == 2);
+ assert(indices_view[3] == 3);
+ assert(indices_view[4] == 4);
+ }
+
+ {
+ std::vector v(5, SomeInt{});
+
+ // Check that the indices view works as expected
+ auto indices_view = std::ranges::views::indices(std::ranges::size(v));
+ assert(indices_view.size() == 5);
+
+ // Check that the view is a range
+ static_assert(std::ranges::range<decltype(indices_view)>);
+
+ // This should be valid, as indices_view is a range of integers
+ assert(indices_view[0] == 0);
+ assert(indices_view[1] == 1);
+ assert(indices_view[2] == 2);
+ assert(indices_view[3] == 3);
+ assert(indices_view[4] == 4);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test_SFIANE();
+
+ test();
+ static_assert(test());
+
+ return 0;
+}
>From 5e04a2e352acf783d6c5aa89580daf60395e03a7 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 3 Jul 2025 09:41:11 +0300
Subject: [PATCH 03/12] Update version
---
libcxx/docs/FeatureTestMacroTable.rst | 2 +
libcxx/include/version | 2 +
.../ranges.version.compile.pass.cpp | 27 +++++
.../version.version.compile.pass.cpp | 27 +++++
.../range.iota.view/indices.pass.cpp | 105 +-----------------
.../generate_feature_test_macro_components.py | 5 +
6 files changed, 69 insertions(+), 99 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 61805726a4ff0..8c2f38e075d45 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -488,6 +488,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_ranges_concat`` *unimplemented*
---------------------------------------------------------- -----------------
+ ``__cpp_lib_ranges_indices`` ``202506L``
+ ---------------------------------------------------------- -----------------
``__cpp_lib_ratio`` ``202306L``
---------------------------------------------------------- -----------------
``__cpp_lib_rcu`` *unimplemented*
diff --git a/libcxx/include/version b/libcxx/include/version
index d98049bd57046..d0b2e865c75bf 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -205,6 +205,7 @@ __cpp_lib_ranges_chunk_by 202202L <ranges>
__cpp_lib_ranges_concat 202403L <ranges>
__cpp_lib_ranges_contains 202207L <algorithm>
__cpp_lib_ranges_find_last 202207L <algorithm>
+__cpp_lib_ranges_indices 202506L <ranges>
__cpp_lib_ranges_iota 202202L <numeric>
__cpp_lib_ranges_join_with 202202L <ranges>
__cpp_lib_ranges_repeat 202207L <ranges>
@@ -590,6 +591,7 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_out_ptr 202311L
// # define __cpp_lib_philox_engine 202406L
// # define __cpp_lib_ranges_concat 202403L
+# define __cpp_lib_ranges_indices 202506L
# define __cpp_lib_ratio 202306L
// # define __cpp_lib_rcu 202306L
# define __cpp_lib_reference_wrapper 202403L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
index df19f03e7dba1..5116864879485 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
@@ -48,6 +48,10 @@
# error "__cpp_lib_ranges_concat should not be defined before c++26"
# endif
+# ifdef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should not be defined before c++26"
+# endif
+
# ifdef __cpp_lib_ranges_join_with
# error "__cpp_lib_ranges_join_with should not be defined before c++23"
# endif
@@ -98,6 +102,10 @@
# error "__cpp_lib_ranges_concat should not be defined before c++26"
# endif
+# ifdef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should not be defined before c++26"
+# endif
+
# ifdef __cpp_lib_ranges_join_with
# error "__cpp_lib_ranges_join_with should not be defined before c++23"
# endif
@@ -148,6 +156,10 @@
# error "__cpp_lib_ranges_concat should not be defined before c++26"
# endif
+# ifdef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should not be defined before c++26"
+# endif
+
# ifdef __cpp_lib_ranges_join_with
# error "__cpp_lib_ranges_join_with should not be defined before c++23"
# endif
@@ -201,6 +213,10 @@
# error "__cpp_lib_ranges_concat should not be defined before c++26"
# endif
+# ifdef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should not be defined before c++26"
+# endif
+
# ifdef __cpp_lib_ranges_join_with
# error "__cpp_lib_ranges_join_with should not be defined before c++23"
# endif
@@ -278,6 +294,10 @@
# error "__cpp_lib_ranges_concat should not be defined before c++26"
# endif
+# ifdef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should not be defined before c++26"
+# endif
+
# ifndef __cpp_lib_ranges_join_with
# error "__cpp_lib_ranges_join_with should be defined in c++23"
# endif
@@ -400,6 +420,13 @@
# endif
# endif
+# ifndef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should be defined in c++26"
+# endif
+# if __cpp_lib_ranges_indices != 202506L
+# error "__cpp_lib_ranges_indices should have the value 202506L in c++26"
+# endif
+
# ifndef __cpp_lib_ranges_join_with
# error "__cpp_lib_ranges_join_with should be defined in c++26"
# endif
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 962688e06188a..36c3ac86c5d86 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -664,6 +664,10 @@
# error "__cpp_lib_ranges_find_last should not be defined before c++23"
# endif
+# ifdef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should not be defined before c++26"
+# endif
+
# ifdef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should not be defined before c++23"
# endif
@@ -1604,6 +1608,10 @@
# error "__cpp_lib_ranges_find_last should not be defined before c++23"
# endif
+# ifdef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should not be defined before c++26"
+# endif
+
# ifdef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should not be defined before c++23"
# endif
@@ -2715,6 +2723,10 @@
# error "__cpp_lib_ranges_find_last should not be defined before c++23"
# endif
+# ifdef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should not be defined before c++26"
+# endif
+
# ifdef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should not be defined before c++23"
# endif
@@ -4099,6 +4111,10 @@
# error "__cpp_lib_ranges_find_last should not be defined before c++23"
# endif
+# ifdef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should not be defined before c++26"
+# endif
+
# ifdef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should not be defined before c++23"
# endif
@@ -5678,6 +5694,10 @@
# error "__cpp_lib_ranges_find_last should have the value 202207L in c++23"
# endif
+# ifdef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should not be defined before c++26"
+# endif
+
# ifndef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should be defined in c++23"
# endif
@@ -7602,6 +7622,13 @@
# error "__cpp_lib_ranges_find_last should have the value 202207L in c++26"
# endif
+# ifndef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should be defined in c++26"
+# endif
+# if __cpp_lib_ranges_indices != 202506L
+# error "__cpp_lib_ranges_indices should have the value 202506L in c++26"
+# endif
+
# ifndef __cpp_lib_ranges_iota
# error "__cpp_lib_ranges_iota should be defined in c++26"
# endif
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
index 01806c27a896f..12f92eed7171f 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
@@ -19,86 +19,11 @@
#include "types.h"
-// #include <compare>
-
-// class IntegerLike {
-// int value;
-
-// public:
-// // Constructor
-// IntegerLike(int v = 0) : value(v) {}
-
-// // Conversion to int
-// operator int() const { return value; }
-
-// // Conversion to std::size_t
-// // This is necessary for std::ranges::views::indices to work with IntegerLike
-// operator std::size_t() const { return static_cast<std::size_t>(value); }
-
-// // Equality and comparison
-// auto operator<=>(const IntegerLike&) const = default;
-
-// // Arithmetic
-// IntegerLike operator+(const IntegerLike& other) const { return IntegerLike(value + other.value); }
-
-// IntegerLike operator-(const IntegerLike& other) const { return IntegerLike(value - other.value); }
-
-// IntegerLike operator*(const IntegerLike& other) const { return IntegerLike(value * other.value); }
-
-// IntegerLike operator/(const IntegerLike& other) const { return IntegerLike(value / other.value); }
-
-// // Compound assignment
-// IntegerLike& operator+=(const IntegerLike& other) {
-// value += other.value;
-// return *this;
-// }
-
-// IntegerLike& operator-=(const IntegerLike& other) {
-// value -= other.value;
-// return *this;
-// }
-
-// IntegerLike& operator*=(const IntegerLike& other) {
-// value *= other.value;
-// return *this;
-// }
-
-// IntegerLike& operator/=(const IntegerLike& other) {
-// value /= other.value;
-// return *this;
-// }
-
-// // Increment / Decrement
-// IntegerLike& operator++() {
-// ++value;
-// return *this;
-// }
-
-// IntegerLike operator++(int) {
-// IntegerLike tmp = *this;
-// ++(*this);
-// return tmp;
-// }
-
-// IntegerLike& operator--() {
-// --value;
-// return *this;
-// }
-
-// IntegerLike operator--(int) {
-// IntegerLike tmp = *this;
-// --(*this);
-// return tmp;
-// }
-// };
-
// Test SFINAE.
template <typename SizeType>
concept HasIndices = requires(SizeType s) { std::ranges::views::indices(s); };
-struct NotIntegerLike {};
-
struct IntegerTypesTest {
template <class T>
constexpr void operator()() {
@@ -106,10 +31,13 @@ struct IntegerTypesTest {
}
};
+struct NotIntegerLike {};
+
void test_SFIANE() {
static_assert(HasIndices<std::size_t>);
types::for_each(types::integer_types(), IntegerTypesTest{});
+ // Not integer-like types should not satisfy HasIndices
static_assert(!HasIndices<bool>);
static_assert(!HasIndices<float>);
static_assert(!HasIndices<void>);
@@ -119,48 +47,28 @@ void test_SFIANE() {
constexpr bool test() {
{
- // Check that the indices view works as expected
auto indices_view = std::ranges::views::indices(5);
assert(indices_view.size() == 5);
- // This should be valid, as indices_view is a range of integers
+ // Check that the view is a range
+ static_assert(std::ranges::range<decltype(indices_view)>);
+
assert(indices_view[0] == 0);
assert(indices_view[1] == 1);
assert(indices_view[2] == 2);
assert(indices_view[3] == 3);
assert(indices_view[4] == 4);
-
- // Check that the view is a range
- static_assert(std::ranges::range<decltype(indices_view)>);
}
- // {
- // // Check that the indices view works as expected
- // auto indices_view = std::ranges::views::indices(IntegerLike{5});
- // assert(indices_view.size() == 5);
-
- // // Check that the view is a range
- // static_assert(std::ranges::range<decltype(indices_view)>);
-
- // // This should be valid, as indices_view is a range of integers
- // assert(indices_view[0] == 0);
- // assert(indices_view[1] == 1);
- // assert(indices_view[2] == 2);
- // assert(indices_view[3] == 3);
- // assert(indices_view[4] == 4);
- // }
-
{
std::vector v(5, 0);
- // Check that the indices view works as expected
auto indices_view = std::ranges::views::indices(std::ranges::size(v));
assert(indices_view.size() == 5);
// Check that the view is a range
static_assert(std::ranges::range<decltype(indices_view)>);
- // This should be valid, as indices_view is a range of integers
assert(indices_view[0] == 0);
assert(indices_view[1] == 1);
assert(indices_view[2] == 2);
@@ -178,7 +86,6 @@ constexpr bool test() {
// Check that the view is a range
static_assert(std::ranges::range<decltype(indices_view)>);
- // This should be valid, as indices_view is a range of integers
assert(indices_view[0] == 0);
assert(indices_view[1] == 1);
assert(indices_view[2] == 2);
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index fe175fd758726..7d5dd984b3fd5 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1116,6 +1116,11 @@ def add_version_header(tc):
"values": {"c++23": 202207},
"headers": ["algorithm"],
},
+ {
+ "name": "__cpp_lib_ranges_indices",
+ "values": {"c++26": 202506},
+ "headers": ["ranges"],
+ },
{
"name": "__cpp_lib_ranges_iota",
"values": {"c++23": 202202},
>From 225dd4c5fc928fbcda2a0c8b2e0c2d0afeb126fb Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 3 Jul 2025 09:46:13 +0300
Subject: [PATCH 04/12] Add release notes
---
libcxx/docs/ReleaseNotes/21.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst
index d31ca0130cb80..1901560857cc7 100644
--- a/libcxx/docs/ReleaseNotes/21.rst
+++ b/libcxx/docs/ReleaseNotes/21.rst
@@ -53,6 +53,7 @@ Implemented Papers
- P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github <https://github.com/llvm/llvm-project/issues/105252>`__)
- P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github <https://github.com/llvm/llvm-project/issues/105250>`__)
- P2655R3: ``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type (`Github <https://github.com/llvm/llvm-project/issues/105260>`__)
+- P3060R2: Add ``std::views::indices(n)``
Improvements and New Features
-----------------------------
>From 2a14a04ce80d653fe22a00ad56ec28dce4ac7389 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 3 Jul 2025 09:48:44 +0300
Subject: [PATCH 05/12] Cleanup
---
libcxx/include/__ranges/iota_view.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index 732a501c07857..c477fadce31f2 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -371,7 +371,6 @@ template <class _Start, class _BoundSentinel>
inline constexpr bool enable_borrowed_range<iota_view<_Start, _BoundSentinel>> = true;
namespace views {
-
namespace __iota {
struct __fn {
template <class _Start>
>From 69d4edd045d9eeabf2975985573ad0db716650bc Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 3 Jul 2025 09:55:43 +0300
Subject: [PATCH 06/12] House keeping
---
libcxx/include/ranges | 5 +++++
.../ranges/range.factories/range.iota.view/indices.pass.cpp | 4 ++++
2 files changed, 9 insertions(+)
diff --git a/libcxx/include/ranges b/libcxx/include/ranges
index 96d7a6b897188..cfaa66a0831b3 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -267,6 +267,11 @@ namespace std::ranges {
template<class W, class Bound>
inline constexpr bool enable_borrowed_range<iota_view<W, Bound>> = true;
+ namespace views {
+ inline constexpr unspecified iota = unspecified;
+ inline constexpr unspecified indices = unspecified; // Since C++26
+ }
+
// [range.repeat], repeat view
template<class T>
concept integer-like-with-usable-difference-type = // exposition only
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
index 12f92eed7171f..3d4b2bbbb89f9 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
@@ -8,6 +8,10 @@
// REQUIRES: std-at-least-c++26
+// ranges
+
+// inline constexpr unspecified indices = unspecified;
+
#include <cassert>
#include <cstddef>
#include <ranges>
>From 4ccd8f9708ddcbe616a874ee504795feaa39f2e2 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 3 Jul 2025 23:25:51 +0300
Subject: [PATCH 07/12] Addressed review comments
---
libcxx/docs/ReleaseNotes/21.rst | 2 +-
libcxx/include/__ranges/iota_view.h | 1 -
libcxx/modules/std/ranges.inc | 3 +++
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst
index 1901560857cc7..edb9a96edf9bd 100644
--- a/libcxx/docs/ReleaseNotes/21.rst
+++ b/libcxx/docs/ReleaseNotes/21.rst
@@ -53,7 +53,7 @@ Implemented Papers
- P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github <https://github.com/llvm/llvm-project/issues/105252>`__)
- P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github <https://github.com/llvm/llvm-project/issues/105250>`__)
- P2655R3: ``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type (`Github <https://github.com/llvm/llvm-project/issues/105260>`__)
-- P3060R2: Add ``std::views::indices(n)``
+- P3060R3: Add ``std::views::indices(n)``
Improvements and New Features
-----------------------------
diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index c477fadce31f2..7593de9fa8b88 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -393,7 +393,6 @@ inline namespace __cpo {
inline constexpr auto iota = __iota::__fn{};
} // namespace __cpo
-
# if _LIBCPP_STD_VER >= 26
inline constexpr auto indices = [](__integer_like auto __size) {
diff --git a/libcxx/modules/std/ranges.inc b/libcxx/modules/std/ranges.inc
index 7ede42e4f7b0a..4b562299debd7 100644
--- a/libcxx/modules/std/ranges.inc
+++ b/libcxx/modules/std/ranges.inc
@@ -114,6 +114,9 @@ export namespace std {
namespace views {
using std::ranges::views::iota;
+#if _LIBCPP_STD_VER >= 23
+ using std::ranges::views::indices;
+#endif
} // namespace views
#if _LIBCPP_STD_VER >= 23
>From b0c1c6567151c5f879ca562f1b135f509aed361d Mon Sep 17 00:00:00 2001
From: Hristo Hristov <zingam at outlook.com>
Date: Fri, 4 Jul 2025 06:45:00 +0300
Subject: [PATCH 08/12] Update libcxx/modules/std/ranges.inc
Co-authored-by: A. Jiang <de34 at live.cn>
---
libcxx/modules/std/ranges.inc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/modules/std/ranges.inc b/libcxx/modules/std/ranges.inc
index 4b562299debd7..cc7daa3cd1aec 100644
--- a/libcxx/modules/std/ranges.inc
+++ b/libcxx/modules/std/ranges.inc
@@ -114,7 +114,7 @@ export namespace std {
namespace views {
using std::ranges::views::iota;
-#if _LIBCPP_STD_VER >= 23
+#if _LIBCPP_STD_VER >= 26
using std::ranges::views::indices;
#endif
} // namespace views
>From 4462459a79cd40a8738b660e70d43b2a075737cb Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 4 Jul 2025 08:02:21 +0300
Subject: [PATCH 09/12] Add CPO test
---
.../customization.point.object/cpo.compile.pass.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp b/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp
index 4e24dbe810165..5cd39a4140905 100644
--- a/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp
+++ b/libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp
@@ -81,6 +81,9 @@ static_assert(test(std::ranges::ssize, a));
// views::empty<T> is not a CPO
static_assert(test(std::views::iota, 1));
static_assert(test(std::views::iota, 1, 10));
+#if TEST_STD_VER >= 26
+static_assert(test(std::views::indices, 10));
+#endif
//static_assert(test(std::views::istream<int>, 1);
static_assert(test(std::views::single, 4));
>From 9926713a03849c0861188c44a252d606eb612293 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 4 Jul 2025 10:52:50 +0300
Subject: [PATCH 10/12] Made the lambda `static`
---
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 7593de9fa8b88..2fca20eacb1dc 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -395,7 +395,7 @@ inline constexpr auto iota = __iota::__fn{};
# if _LIBCPP_STD_VER >= 26
-inline constexpr auto indices = [](__integer_like auto __size) {
+inline constexpr auto indices = [](__integer_like auto __size) static {
return ranges::views::iota(decltype(__size){}, __size);
};
>From ba59dcf62dc0dd2422abe242b22fcc29fe3ac2cf Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 13 Jul 2025 08:40:09 +0300
Subject: [PATCH 11/12] Updated status
---
libcxx/docs/Status/Cxx2cPapers.csv | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index febb0c176f9c4..dab154692147a 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -149,7 +149,7 @@
"`P3503R3 <https://wg21.link/P3503R3>`__","Make type-erased allocator use in ``promise`` and ``packaged_task`` consistent","2025-06 (Sofia)","","",""
"`P3008R6 <https://wg21.link/P3008R6>`__","Atomic floating-point min/max","2025-06 (Sofia)","","",""
"`P3111R8 <https://wg21.link/P3111R8>`__","Atomic Reduction Operations","2025-06 (Sofia)","","",""
-"`P3060R3 <https://wg21.link/P3060R3>`__","Add ``std::views::indices(n)``","2025-06 (Sofia)","","",""
+"`P3060R3 <https://wg21.link/P3060R3>`__","Add ``std::views::indices(n)``","2025-06 (Sofia)","|Complete|","21",""
"`P2319R5 <https://wg21.link/P2319R5>`__","Prevent ``path`` presentation problems","2025-06 (Sofia)","","",""
"`P3223R2 <https://wg21.link/P3223R2>`__","Making ``std::istream::ignore`` less surprising","2025-06 (Sofia)","","",""
"`P2781R9 <https://wg21.link/P2781R9>`__","``std::constant_wrapper``","2025-06 (Sofia)","","",""
>From 1406f636dd1889ca247cb016f9ff21d21acae2c7 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 13 Jul 2025 08:44:10 +0300
Subject: [PATCH 12/12] Update test
---
.../range.iota.view/indices.pass.cpp | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
index 3d4b2bbbb89f9..1f5fab0bbb8f2 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
@@ -41,7 +41,7 @@ void test_SFIANE() {
static_assert(HasIndices<std::size_t>);
types::for_each(types::integer_types(), IntegerTypesTest{});
- // Not integer-like types should not satisfy HasIndices
+ // Non-integer-like types should not satisfy HasIndices
static_assert(!HasIndices<bool>);
static_assert(!HasIndices<float>);
static_assert(!HasIndices<void>);
@@ -52,11 +52,10 @@ void test_SFIANE() {
constexpr bool test() {
{
auto indices_view = std::ranges::views::indices(5);
- assert(indices_view.size() == 5);
-
- // Check that the view is a range
static_assert(std::ranges::range<decltype(indices_view)>);
+ assert(indices_view.size() == 5);
+
assert(indices_view[0] == 0);
assert(indices_view[1] == 1);
assert(indices_view[2] == 2);
@@ -68,11 +67,10 @@ constexpr bool test() {
std::vector v(5, 0);
auto indices_view = std::ranges::views::indices(std::ranges::size(v));
- assert(indices_view.size() == 5);
-
- // Check that the view is a range
static_assert(std::ranges::range<decltype(indices_view)>);
+ assert(indices_view.size() == 5);
+
assert(indices_view[0] == 0);
assert(indices_view[1] == 1);
assert(indices_view[2] == 2);
@@ -83,13 +81,11 @@ constexpr bool test() {
{
std::vector v(5, SomeInt{});
- // Check that the indices view works as expected
auto indices_view = std::ranges::views::indices(std::ranges::size(v));
- assert(indices_view.size() == 5);
-
- // Check that the view is a range
static_assert(std::ranges::range<decltype(indices_view)>);
+ assert(indices_view.size() == 5);
+
assert(indices_view[0] == 0);
assert(indices_view[1] == 1);
assert(indices_view[2] == 2);
More information about the libcxx-commits
mailing list