From 251a81346d2e0aef6743c67a3b7f8e38481942f4 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 07:54:53 +0300 Subject: [PATCH 01/10] [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 // standard-mandated includes From 5e9293a4d7831653fa03e06177fa575e1f2f34a0 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 09:31:14 +0300 Subject: [PATCH 02/10] 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 inline constexpr bool enable_borrowed_range> = true; namespace views { + namespace __iota { struct __fn { template @@ -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 // 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 +#include +#include +#include + +#include "test_macros.h" +#define TEST_HAS_NO_INT128 // Size cannot be larger than 64 bits +#include "type_algorithms.h" + +#include "types.h" + +// #include + +// 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(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 +concept HasIndices = requires(SizeType s) { std::ranges::views::indices(s); }; + +struct NotIntegerLike {}; + +struct IntegerTypesTest { + template + constexpr void operator()() { + static_assert(HasIndices); + } +}; + +void test_SFIANE() { + static_assert(HasIndices); + types::for_each(types::integer_types(), IntegerTypesTest{}); + + static_assert(!HasIndices); + static_assert(!HasIndices); + static_assert(!HasIndices); + static_assert(!HasIndices); // Does satisfy is_integer_like, but not the conversion to std::size_t + static_assert(!HasIndices); +} + +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); + } + + // { + // // 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); + + // // 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); + + // 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); + + // 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 Date: Thu, 3 Jul 2025 09:41:11 +0300 Subject: [PATCH 03/10] 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 __cpp_lib_ranges_concat 202403L __cpp_lib_ranges_contains 202207L __cpp_lib_ranges_find_last 202207L +__cpp_lib_ranges_indices 202506L __cpp_lib_ranges_iota 202202L __cpp_lib_ranges_join_with 202202L __cpp_lib_ranges_repeat 202207L @@ -586,6 +587,7 @@ __cpp_lib_void_t 201411L # 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 - -// 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(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 concept HasIndices = requires(SizeType s) { std::ranges::views::indices(s); }; -struct NotIntegerLike {}; - struct IntegerTypesTest { template constexpr void operator()() { @@ -106,10 +31,13 @@ struct IntegerTypesTest { } }; +struct NotIntegerLike {}; + void test_SFIANE() { static_assert(HasIndices); types::for_each(types::integer_types(), IntegerTypesTest{}); + // Not integer-like types should not satisfy HasIndices static_assert(!HasIndices); static_assert(!HasIndices); static_assert(!HasIndices); @@ -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); + 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); } - // { - // // 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); - - // // 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); - // 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); - // 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 Date: Thu, 3 Jul 2025 09:46:13 +0300 Subject: [PATCH 04/10] 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 `__) - P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github `__) - P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github `__) +- P3060R2: Add ``std::views::indices(n)`` Improvements and New Features ----------------------------- From 207fb0cb513815ad3ca5da82b82e0a2a0cd9f117 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 09:48:44 +0300 Subject: [PATCH 05/10] 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 inline constexpr bool enable_borrowed_range> = true; namespace views { - namespace __iota { struct __fn { template From 0f2b6cde9219a4eb148fca97410df0de54050ee6 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 09:55:43 +0300 Subject: [PATCH 06/10] 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 inline constexpr bool enable_borrowed_range> = true; + namespace views { + inline constexpr unspecified iota = unspecified; + inline constexpr unspecified indices = unspecified; // Since C++26 + } + // [range.repeat], repeat view template 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 #include #include From cc3f700ef2e872b3c693b2ec9b47f8a66f9f97ce Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 23:25:51 +0300 Subject: [PATCH 07/10] 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 7e525a21380ec..7162c9a7a6ba8 100644 --- a/libcxx/docs/ReleaseNotes/21.rst +++ b/libcxx/docs/ReleaseNotes/21.rst @@ -51,7 +51,7 @@ Implemented Papers - P2441R2: ``views::join_with`` (`Github `__) - P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github `__) - P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github `__) -- 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 adabeeb22d551..558dc9edbff81 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 c1981bd9806aa4ab63f95b7d27a1b2b1679acfec Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 4 Jul 2025 06:45:00 +0300 Subject: [PATCH 08/10] Update libcxx/modules/std/ranges.inc Co-authored-by: A. Jiang --- 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 558dc9edbff81..c1b677da6d7bb 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 8e48a6cec3ccd2501708031eaa0b3c48ba01cc52 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 4 Jul 2025 08:02:21 +0300 Subject: [PATCH 09/10] Add CPO test --- .../customization.point.object/cpo.compile.pass.cpp | 5 +++++ 1 file changed, 5 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 3f4317a724add..b362753106aad 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 @@ -18,6 +18,8 @@ #include #include +#include "test_macros.h" + // Test for basic properties of C++20 16.3.3.3.6 [customization.point.object]. template constexpr bool test(CPO& o, Args&&...) { @@ -79,6 +81,9 @@ static_assert(test(std::ranges::ssize, a)); // views::empty 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, 1); static_assert(test(std::views::single, 4)); From 0c947c47fe846abbdfb9b57442057363502cb7c3 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 4 Jul 2025 10:52:50 +0300 Subject: [PATCH 10/10] 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); };