Skip to content

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

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions libcxx/docs/FeatureTestMacroTable.rst
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_ranges_concat`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_ranges_indices`` ``202506L``
---------------------------------------------------------- -----------------
``__cpp_lib_ratio`` ``202306L``
---------------------------------------------------------- -----------------
``__cpp_lib_rcu`` *unimplemented*
Expand Down
1 change: 1 addition & 0 deletions libcxx/docs/ReleaseNotes/21.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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>`__)
- P3060R3: Add ``std::views::indices(n)``

Improvements and New Features
-----------------------------
Expand Down
9 changes: 9 additions & 0 deletions libcxx/include/__ranges/iota_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 5 additions & 0 deletions libcxx/include/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions libcxx/include/version
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions libcxx/modules/std/ranges.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include <type_traits>
#include <utility>

#include "test_macros.h"

// Test for basic properties of C++20 16.3.3.3.6 [customization.point.object].
template <class CPO, class... Args>
constexpr bool test(CPO& o, Args&&...) {
Expand Down Expand Up @@ -79,6 +81,9 @@ static_assert(test(std::ranges::ssize, a));
// views::empty<T> 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<int>, 1);
static_assert(test(std::views::single, 4));

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
5 changes: 5 additions & 0 deletions libcxx/utils/generate_feature_test_macro_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down
Loading