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..7162c9a7a6ba8 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 `__) +- 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 4b84585258b91..2fca20eacb1dc 100644 --- a/libcxx/include/__ranges/iota_view.h +++ b/libcxx/include/__ranges/iota_view.h @@ -392,6 +392,15 @@ 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) static { + 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 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/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/modules/std/ranges.inc b/libcxx/modules/std/ranges.inc index adabeeb22d551..c1b677da6d7bb 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 >= 26 + using std::ranges::views::indices; +#endif } // namespace views #if _LIBCPP_STD_VER >= 23 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/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)); 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 +#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" + +// Test SFINAE. + +template +concept HasIndices = requires(SizeType s) { std::ranges::views::indices(s); }; + +struct IntegerTypesTest { + template + constexpr void operator()() { + static_assert(HasIndices); + } +}; + +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); + static_assert(!HasIndices); // Does satisfy is_integer_like, but not the conversion to std::size_t + static_assert(!HasIndices); +} + +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[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); + + 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); + + 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},