[libcxx-commits] [libcxx] 45c4124 - [libc++][ranges] P3060R3: Add `std::views::indices(n)` (#146823)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Oct 6 08:13:30 PDT 2025


Author: Hristo Hristov
Date: 2025-10-06T18:13:25+03:00
New Revision: 45c41247f82e5691425542de829d568cdc2fb580

URL: https://github.com/llvm/llvm-project/commit/45c41247f82e5691425542de829d568cdc2fb580
DIFF: https://github.com/llvm/llvm-project/commit/45c41247f82e5691425542de829d568cdc2fb580.diff

LOG: [libc++][ranges] P3060R3: Add `std::views::indices(n)` (#146823)

Implements [P3060R3](https://wg21.link/P3060R3)

Closes #148175

# References

- https://github.com/cplusplus/draft/issues/7966
- https://github.com/cplusplus/draft/pull/8006
- https://wg21.link/customization.point.object
- https://wg21.link/range.iota.overview
- https://wg21.link/ranges.syn

---------

Co-authored-by: Hristo Hristov <zingam at outlook.com>
Co-authored-by: A. Jiang <de34 at live.cn>

Added: 
    libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp

Modified: 
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/docs/ReleaseNotes/22.rst
    libcxx/docs/Status/Cxx2cPapers.csv
    libcxx/include/__ranges/iota_view.h
    libcxx/include/ranges
    libcxx/include/version
    libcxx/modules/std/ranges.inc
    libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
    libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 3c7175c73f21e..c7f01e6868395 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/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 8d023a14e89e6..ec23ba9d1e3a1 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -42,6 +42,7 @@ Implemented Papers
   is implemented in this release)
 - P3044R2: sub-``string_view`` from ``string`` (`Github <https://llvm.org/PR148140>`__)
 - P3223R2: Making ``std::istream::ignore`` less surprising (`Github <https://llvm.org/PR148178>`__)
+- P3060R3: Add ``std::views::indices(n)`` (`Github <https://llvm.org/PR148175>`__)
 - P3168R2: Give ``std::optional`` Range Support (`Github <https://llvm.org/PR105430>`__)
 
 Improvements and New Features

diff  --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 4e0918b0246c1..69b9984f43ccf 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)","","","`#148164 <https://github.com/llvm/llvm-project/issues/148164>`__",""
 "`P3008R6 <https://wg21.link/P3008R6>`__","Atomic floating-point min/max","2025-06 (Sofia)","","","`#148168 <https://github.com/llvm/llvm-project/issues/148168>`__",""
 "`P3111R8 <https://wg21.link/P3111R8>`__","Atomic Reduction Operations","2025-06 (Sofia)","","","`#148174 <https://github.com/llvm/llvm-project/issues/148174>`__",""
-"`P3060R3 <https://wg21.link/P3060R3>`__","Add ``std::views::indices(n)``","2025-06 (Sofia)","","","`#148175 <https://github.com/llvm/llvm-project/issues/148175>`__",""
+"`P3060R3 <https://wg21.link/P3060R3>`__","Add ``std::views::indices(n)``","2025-06 (Sofia)","|Complete|","22","`#148175 <https://github.com/llvm/llvm-project/issues/148175>`__",""
 "`P2319R5 <https://wg21.link/P2319R5>`__","Prevent ``path`` presentation problems","2025-06 (Sofia)","","","`#148177 <https://github.com/llvm/llvm-project/issues/148177>`__",""
 "`P3223R2 <https://wg21.link/P3223R2>`__","Making ``std::istream::ignore`` less surprising","2025-06 (Sofia)","|Complete|","22","`#148178 <https://github.com/llvm/llvm-project/issues/148178>`__",""
 "`P2781R9 <https://wg21.link/P2781R9>`__","``std::constant_wrapper``","2025-06 (Sofia)","","","`#148179 <https://github.com/llvm/llvm-project/issues/148179>`__",""

diff  --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index 32ff3408e54ea..22adc22e69190 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -393,6 +393,15 @@ 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) static {
+  return ranges::views::iota(decltype(__size){}, __size);
+};
+
+#  endif
+
 } // namespace views
 } // namespace ranges
 

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-
diff erence-type =  // exposition only

diff  --git a/libcxx/include/version b/libcxx/include/version
index a132f0808aeb8..99e69299921fa 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>
@@ -591,6 +592,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/modules/std/ranges.inc b/libcxx/modules/std/ranges.inc
index 7ede42e4f7b0a..cc7daa3cd1aec 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 >= 26
+      using std::ranges::views::indices;
+#endif
     } // namespace views
 
 #if _LIBCPP_STD_VER >= 23

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 6aa704a3ead3f..9a8a1da88ee8f 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
@@ -1608,6 +1612,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
@@ -2723,6 +2731,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
@@ -4111,6 +4123,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
@@ -5694,6 +5710,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
@@ -7610,6 +7630,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/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 49497875dcf95..7e2510f5b5d13 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
@@ -89,6 +89,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
 #ifndef TEST_HAS_NO_LOCALIZATION
 static_assert(test(std::views::istream<int>, stream));
 #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
new file mode 100644
index 0000000000000..d92b6cb876a40
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
@@ -0,0 +1,97 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// ranges
+
+// inline constexpr unspecified indices = unspecified;
+
+#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"
+
+// Test SFINAE.
+
+template <typename SizeType>
+concept HasIndices = requires(SizeType s) { std::ranges::views::indices(s); };
+
+struct NotIntegerLike {};
+
+void test_SFINAE() {
+  static_assert(HasIndices<std::size_t>);
+  types::for_each(types::integer_types(), []<typename T> { static_assert(HasIndices<T>); });
+
+  // Non-integer-like types should not satisfy HasIndices
+  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() {
+  {
+    auto indices_view = std::ranges::views::indices(5);
+    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);
+    assert(indices_view[3] == 3);
+    assert(indices_view[4] == 4);
+  }
+
+  {
+    std::vector v(5, 0);
+
+    auto indices_view = std::ranges::views::indices(std::ranges::size(v));
+    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);
+    assert(indices_view[3] == 3);
+    assert(indices_view[4] == 4);
+  }
+
+  {
+    std::vector v(5, SomeInt{});
+
+    auto indices_view = std::ranges::views::indices(std::ranges::size(v));
+    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);
+    assert(indices_view[3] == 3);
+    assert(indices_view[4] == 4);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 5d469d4914b0b..2d5b66d994da0 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1113,6 +1113,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},


        


More information about the libcxx-commits mailing list