Skip to content

Conversation

H-G-Hristov
Copy link
Contributor

@H-G-Hristov H-G-Hristov commented Jul 3, 2025

Copy link

github-actions bot commented Jul 3, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@Zingam Zingam added libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. c++26 labels Jul 3, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 3, 2025

@llvm/pr-subscribers-libcxx

Author: Hristo Hristov (H-G-Hristov)

Changes

Implements P3060R2

References


This implements only P3060R2


Full diff: https://github.com/llvm/llvm-project/pull/146823.diff

9 Files Affected:

  • (modified) libcxx/docs/FeatureTestMacroTable.rst (+2)
  • (modified) libcxx/docs/ReleaseNotes/21.rst (+1)
  • (modified) libcxx/include/__ranges/iota_view.h (+10)
  • (modified) libcxx/include/ranges (+5)
  • (modified) libcxx/include/version (+2)
  • (modified) libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp (+27)
  • (modified) libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp (+27)
  • (added) libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp (+110)
  • (modified) libcxx/utils/generate_feature_test_macro_components.py (+5)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 3c635e5e46bbd..74ec5936f8598 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -484,6 +484,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/21.rst b/libcxx/docs/ReleaseNotes/21.rst
index 08b32bb508dc1..7e525a21380ec 100644
--- a/libcxx/docs/ReleaseNotes/21.rst
+++ b/libcxx/docs/ReleaseNotes/21.rst
@@ -51,6 +51,7 @@ Implemented Papers
 - P2441R2: ``views::join_with`` (`Github <https://github.com/llvm/llvm-project/issues/105185>`__)
 - 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>`__)
+- P3060R2: 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 4b84585258b91..c477fadce31f2 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -392,6 +392,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/ranges b/libcxx/include/ranges
index 2a6321bd2c5d8..aab708e63e279 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/include/version b/libcxx/include/version
index 91fe48351e161..f46018cdbce13 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -203,6 +203,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>
@@ -586,6 +587,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 4cf5178dd7b8f..ce6d9ee82e66e 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 e546719142231..67f98ef933ab3 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
@@ -656,6 +656,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
@@ -1588,6 +1592,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
@@ -2691,6 +2699,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
@@ -4061,6 +4073,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
@@ -5626,6 +5642,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
@@ -7536,6 +7556,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
new file mode 100644
index 0000000000000..3d4b2bbbb89f9
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/indices.pass.cpp
@@ -0,0 +1,110 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 IntegerTypesTest {
+  template <class T>
+  constexpr void operator()() {
+    static_assert(HasIndices<T>);
+  }
+};
+
+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>);
+  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);
+    assert(indices_view.size() == 5);
+
+    // 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);
+  }
+
+  {
+    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[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)>);
+
+    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;
+}
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index edd7b124a1fb3..df85619605f4a 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1106,6 +1106,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},


# if _LIBCPP_STD_VER >= 26

inline constexpr auto indices = [](__integer_like auto __size) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libcxx/modules/std/ranges.inc should also be changed.

Also, is there any particular reason not to make this lambda static?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about that. Why would we want to mark a CPO lambda static?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear, I'm inclined to make the operator() static, see also #86052. I think this will improve performance in certain circumstances, but also accept non-portable (although harmless) calls on volatile-qualified values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@H-G-Hristov H-G-Hristov changed the title WIP [libc++][ranges] P3060R3 Add std::views::indices(n) WIP [libc++][ranges] P3060R3: Add std::views::indices(n) Jul 4, 2025
@H-G-Hristov H-G-Hristov marked this pull request as ready for review July 13, 2025 05:45
@H-G-Hristov H-G-Hristov requested a review from a team as a code owner July 13, 2025 05:45
@H-G-Hristov H-G-Hristov changed the title WIP [libc++][ranges] P3060R3: Add std::views::indices(n) [libc++][ranges] P3060R3: Add std::views::indices(n) Jul 13, 2025
@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/P3060R3-Add-std_views_indices branch from 9ae7490 to 1406f63 Compare July 22, 2025 17:08
@Zingam Zingam added the ranges Issues related to `<ranges>` label Jul 25, 2025
@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/P3060R3-Add-std_views_indices branch from 75d0616 to ec1fc1a Compare July 25, 2025 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++26 libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. ranges Issues related to `<ranges>`
Projects
None yet
Development

Successfully merging this pull request may close these issues.

P3060R3: Add std::views::indices(n)
4 participants