-
Notifications
You must be signed in to change notification settings - Fork 14.4k
WIP [libc++][ranges] P3060R3: Add std::views::indices(n) #146823
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
WIP [libc++][ranges] P3060R3: Add std::views::indices(n) #146823
Conversation
Implements: P3060R3 # References - cplusplus/draft#7966 - cplusplus/draft#8006 - https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3060r2.html
✅ With the latest revision this PR passed the C/C++ code formatter. |
@llvm/pr-subscribers-libcxx Author: Hristo Hristov (H-G-Hristov) ChangesImplements P3060R2 References
This implements only P3060R2 Full diff: https://github.com/llvm/llvm-project/pull/146823.diff 9 Files Affected:
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},
|
libcxx/include/__ranges/iota_view.h
Outdated
|
||
# if _LIBCPP_STD_VER >= 26 | ||
|
||
inline constexpr auto indices = [](__integer_like auto __size) { |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Co-authored-by: A. Jiang <de34@live.cn>
Implements P3060R3
References