From f81e4a3668c4333a3301c9a8bd463531b0312418 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 07:54:53 +0300 Subject: [PATCH 01/14] [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 ed5475141b50a..2f0df51b3b827 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -714,6 +714,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 117556edb5d20..f4b9ba62d90ce 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1887,6 +1887,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 96d7a6b897188..f4b7a8a70f43e 100644 --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -453,6 +453,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 3e9593dcbeb7559f70379ed704b9ecad882fb667 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 09:31:14 +0300 Subject: [PATCH 02/14] 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 2f0df51b3b827..ed5475141b50a 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -714,7 +714,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 f4b9ba62d90ce..117556edb5d20 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1887,7 +1887,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 f4b7a8a70f43e..96d7a6b897188 100644 --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -453,10 +453,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 1572f7a93abc26988d457a2b9d43eb66e638568f Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 09:41:11 +0300 Subject: [PATCH 03/14] 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 61805726a4ff0..8c2f38e075d45 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -488,6 +488,8 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_ranges_concat`` *unimplemented* ---------------------------------------------------------- ----------------- + ``__cpp_lib_ranges_indices`` ``202506L`` + ---------------------------------------------------------- ----------------- ``__cpp_lib_ratio`` ``202306L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_rcu`` *unimplemented* diff --git a/libcxx/include/version b/libcxx/include/version index d98049bd57046..d0b2e865c75bf 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -205,6 +205,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 @@ -590,6 +591,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 df19f03e7dba1..5116864879485 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp @@ -48,6 +48,10 @@ # error "__cpp_lib_ranges_concat should not be defined before c++26" # endif +# ifdef __cpp_lib_ranges_indices +# error "__cpp_lib_ranges_indices should not be defined before c++26" +# endif + # ifdef __cpp_lib_ranges_join_with # error "__cpp_lib_ranges_join_with should not be defined before c++23" # endif @@ -98,6 +102,10 @@ # error "__cpp_lib_ranges_concat should not be defined before c++26" # endif +# ifdef __cpp_lib_ranges_indices +# error "__cpp_lib_ranges_indices should not be defined before c++26" +# endif + # ifdef __cpp_lib_ranges_join_with # error "__cpp_lib_ranges_join_with should not be defined before c++23" # endif @@ -148,6 +156,10 @@ # error "__cpp_lib_ranges_concat should not be defined before c++26" # endif +# ifdef __cpp_lib_ranges_indices +# error "__cpp_lib_ranges_indices should not be defined before c++26" +# endif + # ifdef __cpp_lib_ranges_join_with # error "__cpp_lib_ranges_join_with should not be defined before c++23" # endif @@ -201,6 +213,10 @@ # error "__cpp_lib_ranges_concat should not be defined before c++26" # endif +# ifdef __cpp_lib_ranges_indices +# error "__cpp_lib_ranges_indices should not be defined before c++26" +# endif + # ifdef __cpp_lib_ranges_join_with # error "__cpp_lib_ranges_join_with should not be defined before c++23" # endif @@ -278,6 +294,10 @@ # error "__cpp_lib_ranges_concat should not be defined before c++26" # endif +# ifdef __cpp_lib_ranges_indices +# error "__cpp_lib_ranges_indices should not be defined before c++26" +# endif + # ifndef __cpp_lib_ranges_join_with # error "__cpp_lib_ranges_join_with should be defined in c++23" # endif @@ -400,6 +420,13 @@ # endif # endif +# ifndef __cpp_lib_ranges_indices +# error "__cpp_lib_ranges_indices should be defined in c++26" +# endif +# if __cpp_lib_ranges_indices != 202506L +# error "__cpp_lib_ranges_indices should have the value 202506L in c++26" +# endif + # ifndef __cpp_lib_ranges_join_with # error "__cpp_lib_ranges_join_with should be defined in c++26" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index 962688e06188a..36c3ac86c5d86 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -664,6 +664,10 @@ # error "__cpp_lib_ranges_find_last should not be defined before c++23" # endif +# ifdef __cpp_lib_ranges_indices +# error "__cpp_lib_ranges_indices should not be defined before c++26" +# endif + # ifdef __cpp_lib_ranges_iota # error "__cpp_lib_ranges_iota should not be defined before c++23" # endif @@ -1604,6 +1608,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 @@ -2715,6 +2723,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 @@ -4099,6 +4111,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 @@ -5678,6 +5694,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 @@ -7602,6 +7622,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 fe175fd758726..7d5dd984b3fd5 100644 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -1116,6 +1116,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 a27ae43fa8e2a3bd2882425719a9b46644508b1b Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 09:46:13 +0300 Subject: [PATCH 04/14] 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 d31ca0130cb80..1901560857cc7 100644 --- a/libcxx/docs/ReleaseNotes/21.rst +++ b/libcxx/docs/ReleaseNotes/21.rst @@ -53,6 +53,7 @@ Implemented Papers - P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github `__) - P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github `__) - P2655R3: ``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type (`Github `__) +- P3060R2: Add ``std::views::indices(n)`` Improvements and New Features ----------------------------- From a6472950559bdc150e98b1264f9b688705a96e56 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 09:48:44 +0300 Subject: [PATCH 05/14] 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 9f06e2967751ecbca92a821d0b7eb06256387b5b Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 09:55:43 +0300 Subject: [PATCH 06/14] 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 96d7a6b897188..cfaa66a0831b3 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 35c85796958b1b6a51ced6431e2ee2aaaac18b94 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 3 Jul 2025 23:25:51 +0300 Subject: [PATCH 07/14] 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 1901560857cc7..edb9a96edf9bd 100644 --- a/libcxx/docs/ReleaseNotes/21.rst +++ b/libcxx/docs/ReleaseNotes/21.rst @@ -53,7 +53,7 @@ Implemented Papers - P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github `__) - P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github `__) - P2655R3: ``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type (`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 7ede42e4f7b0a..4b562299debd7 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 b0c1a8460df7b11580d1d13ed226c9bb75bd0256 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 4 Jul 2025 06:45:00 +0300 Subject: [PATCH 08/14] 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 4b562299debd7..cc7daa3cd1aec 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 4fbdb9f35068bf2648bd41a4eabfd518094c2398 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 4 Jul 2025 10:52:50 +0300 Subject: [PATCH 09/14] 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); }; From 3c5694647f370e902493057fff72eb5e8847cdd0 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Sun, 13 Jul 2025 08:40:09 +0300 Subject: [PATCH 10/14] Updated status --- libcxx/docs/Status/Cxx2cPapers.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index febb0c176f9c4..dab154692147a 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -149,7 +149,7 @@ "`P3503R3 `__","Make type-erased allocator use in ``promise`` and ``packaged_task`` consistent","2025-06 (Sofia)","","","" "`P3008R6 `__","Atomic floating-point min/max","2025-06 (Sofia)","","","" "`P3111R8 `__","Atomic Reduction Operations","2025-06 (Sofia)","","","" -"`P3060R3 `__","Add ``std::views::indices(n)``","2025-06 (Sofia)","","","" +"`P3060R3 `__","Add ``std::views::indices(n)``","2025-06 (Sofia)","|Complete|","21","" "`P2319R5 `__","Prevent ``path`` presentation problems","2025-06 (Sofia)","","","" "`P3223R2 `__","Making ``std::istream::ignore`` less surprising","2025-06 (Sofia)","","","" "`P2781R9 `__","``std::constant_wrapper``","2025-06 (Sofia)","","","" From af7fe91b6dc1225aad166679576c361325e5939f Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Sun, 13 Jul 2025 08:44:10 +0300 Subject: [PATCH 11/14] Update test --- .../range.iota.view/indices.pass.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) 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 3d4b2bbbb89f9..1f5fab0bbb8f2 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 @@ -41,7 +41,7 @@ void test_SFIANE() { static_assert(HasIndices); types::for_each(types::integer_types(), IntegerTypesTest{}); - // Not integer-like types should not satisfy HasIndices + // Non-integer-like types should not satisfy HasIndices static_assert(!HasIndices); static_assert(!HasIndices); static_assert(!HasIndices); @@ -52,11 +52,10 @@ void test_SFIANE() { 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); + assert(indices_view.size() == 5); + assert(indices_view[0] == 0); assert(indices_view[1] == 1); assert(indices_view[2] == 2); @@ -68,11 +67,10 @@ constexpr bool test() { 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); + assert(indices_view.size() == 5); + assert(indices_view[0] == 0); assert(indices_view[1] == 1); assert(indices_view[2] == 2); @@ -83,13 +81,11 @@ constexpr bool test() { { 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); + assert(indices_view.size() == 5); + assert(indices_view[0] == 0); assert(indices_view[1] == 1); assert(indices_view[2] == 2); From cd478e8b57d62e7f2b59e7929983ee04ba6a536b Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Tue, 22 Jul 2025 20:16:46 +0300 Subject: [PATCH 12/14] LLVM22 --- libcxx/docs/ReleaseNotes/21.rst | 1 - libcxx/docs/ReleaseNotes/22.rst | 1 + libcxx/docs/Status/Cxx2cPapers.csv | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst index edb9a96edf9bd..d31ca0130cb80 100644 --- a/libcxx/docs/ReleaseNotes/21.rst +++ b/libcxx/docs/ReleaseNotes/21.rst @@ -53,7 +53,6 @@ Implemented Papers - P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github `__) - P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github `__) - P2655R3: ``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type (`Github `__) -- P3060R3: Add ``std::views::indices(n)`` Improvements and New Features ----------------------------- diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst index 15bf46d44b07f..b2d29c41b9880 100644 --- a/libcxx/docs/ReleaseNotes/22.rst +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -39,6 +39,7 @@ Implemented Papers ------------------ - P2321R2: ``zip`` (`Github `__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release) +- P3060R3: Add ``std::views::indices(n)`` (`Github `__) Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index dab154692147a..fe2c73655a530 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -149,7 +149,7 @@ "`P3503R3 `__","Make type-erased allocator use in ``promise`` and ``packaged_task`` consistent","2025-06 (Sofia)","","","" "`P3008R6 `__","Atomic floating-point min/max","2025-06 (Sofia)","","","" "`P3111R8 `__","Atomic Reduction Operations","2025-06 (Sofia)","","","" -"`P3060R3 `__","Add ``std::views::indices(n)``","2025-06 (Sofia)","|Complete|","21","" +"`P3060R3 `__","Add ``std::views::indices(n)``","2025-06 (Sofia)","|Complete|","22","" "`P2319R5 `__","Prevent ``path`` presentation problems","2025-06 (Sofia)","","","" "`P3223R2 `__","Making ``std::istream::ignore`` less surprising","2025-06 (Sofia)","","","" "`P2781R9 `__","``std::constant_wrapper``","2025-06 (Sofia)","","","" From f0bad15757071dab652f3f071471b25618976325 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Tue, 22 Jul 2025 20:19:06 +0300 Subject: [PATCH 13/14] Update libcxx/docs/ReleaseNotes/22.rst --- libcxx/docs/ReleaseNotes/22.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst index b2d29c41b9880..b0907e8a02c1c 100644 --- a/libcxx/docs/ReleaseNotes/22.rst +++ b/libcxx/docs/ReleaseNotes/22.rst @@ -39,7 +39,7 @@ Implemented Papers ------------------ - P2321R2: ``zip`` (`Github `__) (The paper is partially implemented. ``zip_transform_view`` is implemented in this release) -- P3060R3: Add ``std::views::indices(n)`` (`Github `__) +- P3060R3: Add ``std::views::indices(n)`` (`Github `__) Improvements and New Features ----------------------------- From ec1fc1ab32ee9c2a472c22b83f50d6f6be8001c7 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 25 Jul 2025 21:50:41 +0300 Subject: [PATCH 14/14] Update CPO test --- .../customization.point.object/cpo.compile.pass.cpp | 3 +++ 1 file changed, 3 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 678483b9b2f2f..24d3888d436bc 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 @@ -85,6 +85,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 #ifndef TEST_HAS_NO_LOCALIZATION static_assert(test(std::views::istream, stream)); #endif