[libcxx-commits] [libcxx] WIP [libc++][ranges] P3060R3 Add std::views::indices(n) (PR #146823)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jul 3 00:00:16 PDT 2025
https://github.com/H-G-Hristov created https://github.com/llvm/llvm-project/pull/146823
Implements [P3060R2](https://wg21.link/ )
# References
- https://github.com/cplusplus/draft/issues/7966
- https://github.com/cplusplus/draft/pull/8006
---
This implements only P3060R2
>From 251a81346d2e0aef6743c67a3b7f8e38481942f4 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 1/6] [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 c334b25574305..59728d8c19919 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -704,6 +704,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 b00a8ebd54623..cd9e3982cd93f 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1869,6 +1869,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 2a6321bd2c5d8..32499ea34e3dc 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -442,6 +442,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 5e9293a4d7831653fa03e06177fa575e1f2f34a0 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 2/6] 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 59728d8c19919..c334b25574305 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -704,7 +704,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 cd9e3982cd93f..b00a8ebd54623 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1869,7 +1869,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 32499ea34e3dc..2a6321bd2c5d8 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -442,10 +442,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 e2c569cd5c0a7b0044c07e3f948955e7d381e358 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 3/6] 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 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/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
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 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},
>From aacc52c564b0800ec283c79fe3d2e46138bb903e 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 4/6] 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 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
-----------------------------
>From 207fb0cb513815ad3ca5da82b82e0a2a0cd9f117 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 5/6] 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 0f2b6cde9219a4eb148fca97410df0de54050ee6 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 6/6] 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 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/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>
More information about the libcxx-commits
mailing list