Skip to content
Merged
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
429 changes: 402 additions & 27 deletions stl/inc/ranges

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -774,11 +774,11 @@ concept indirectly_writable = requires(_It&& __i, _Ty&& __t) {
};

// CONCEPT _Integer_like
// clang-format off
template <class _Ty>
concept _Integer_like = _Is_nonbool_integral<_Ty>;
concept _Integer_like = _Is_nonbool_integral<remove_cv_t<_Ty>>;

// CONCEPT _Signed_integer_like
// clang-format off
template <class _Ty>
concept _Signed_integer_like = _Integer_like<_Ty> && static_cast<_Ty>(-1) < static_cast<_Ty>(0);
// clang-format on
Expand All @@ -787,10 +787,20 @@ concept _Signed_integer_like = _Integer_like<_Ty> && static_cast<_Ty>(-1) < stat
template <class _Ty>
using _Make_unsigned_like_t = make_unsigned_t<_Ty>;

template <_Integer_like _Ty>
_NODISCARD constexpr auto _To_unsigned_like(const _Ty _Value) noexcept {
return static_cast<_Make_unsigned_like_t<_Ty>>(_Value);
}

// ALIAS TEMPLATE _Make_signed_like_t
template <class _Ty>
using _Make_signed_like_t = make_signed_t<_Ty>;

template <_Integer_like _Ty>
_NODISCARD constexpr auto _To_signed_like(const _Ty _Value) noexcept {
return static_cast<_Make_signed_like_t<_Ty>>(_Value);
}

// CONCEPT weakly_incrementable
// clang-format off
template <class _Ty>
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ tests\P0896R4_views_elements
tests\P0896R4_views_empty
tests\P0896R4_views_filter
tests\P0896R4_views_filter_death
tests\P0896R4_views_iota
tests\P0896R4_views_reverse
tests\P0896R4_views_single
tests\P0896R4_views_take
Expand Down
5 changes: 2 additions & 3 deletions tests/std/tests/P0896R4_ranges_range_machinery/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ STATIC_ASSERT(test_cpo(ranges::views::drop));
STATIC_ASSERT(test_cpo(ranges::views::drop_while));
STATIC_ASSERT(test_cpo(ranges::views::elements<42>));
STATIC_ASSERT(test_cpo(ranges::views::filter));
STATIC_ASSERT(test_cpo(ranges::views::iota));
STATIC_ASSERT(test_cpo(ranges::views::keys));
STATIC_ASSERT(test_cpo(ranges::views::reverse));
STATIC_ASSERT(test_cpo(ranges::views::single));
Expand Down Expand Up @@ -1499,9 +1500,7 @@ namespace borrowed_range_testing {
STATIC_ASSERT(test_borrowed_range<std::span<int, 42>, std::span<int, 42>::iterator>());
STATIC_ASSERT(test_borrowed_range<ranges::subrange<int*, int*>, int*>());
STATIC_ASSERT(test_borrowed_range<ranges::ref_view<int[42]>, int*>());
#if 0 // TRANSITION, future
STATIC_ASSERT(test_borrowed_range<ranges::iota_view<int, int>, ...>());
#endif // TRANSITION, future
STATIC_ASSERT(test_borrowed_range<ranges::iota_view<int, int>, ranges::iterator_t<ranges::iota_view<int, int>>>());

struct simple_borrowed_range {
int* begin() const {
Expand Down
131 changes: 72 additions & 59 deletions tests/std/tests/P0896R4_views_drop/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,41 +20,58 @@ using namespace std;
constexpr auto pipeline = views::drop(1) | views::drop(1) | views::drop(1) | views::drop(1);

template <class>
inline constexpr bool is_empty_view = false;
template <class T>
inline constexpr bool is_empty_view<ranges::empty_view<T>> = true;

template <class>
inline constexpr bool is_dynamic_span = false;
template <class T>
inline constexpr bool is_dynamic_span<span<T>> = true;

template <class>
inline constexpr bool is_string_view = false;
template <class CharT, class Traits>
inline constexpr bool is_string_view<basic_string_view<CharT, Traits>> = true;
inline constexpr bool is_span = false;
template <class T, size_t N>
inline constexpr bool is_span<span<T, N>> = true;

template <class>
inline constexpr bool is_subrange = false;
template <class I, class S, ranges::subrange_kind K>
inline constexpr bool is_subrange<ranges::subrange<I, S, K>> = true;

template <class>
struct mapped {
template <class Rng>
using apply = ranges::drop_view<views::all_t<Rng>>;
};
template <class T>
struct mapped<ranges::empty_view<T>> {
template <class>
using apply = ranges::empty_view<T>;
};
template <class T, size_t N>
struct mapped<span<T, N>> {
template <class>
using apply = span<T>;
};
template <class CharT, class Traits>
struct mapped<basic_string_view<CharT, Traits>> {
template <class>
using apply = basic_string_view<CharT, Traits>;
};
// clang-format off
template <class W, class B>
requires ranges::random_access_range<ranges::iota_view<W, B>>
&& ranges::sized_range<ranges::iota_view<W, B>>
struct mapped<ranges::iota_view<W, B>> {
// clang-format on
template <class>
using apply = ranges::iota_view<W, B>;
};
// clang-format off
template <class V>
concept reconstructible = ranges::random_access_range<V>
&& ranges::sized_range<V>
&& (is_empty_view<V>
|| is_dynamic_span<V>
|| is_string_view<V>
// || is_iota_view<V> // TRANSITION, iota_view
|| is_subrange<V>);
// clang-format on

template <ranges::view V>
using mapped_t = conditional_t<reconstructible<V>, V, ranges::drop_view<V>>;
template <class I, class S>
requires random_access_iterator<I>
struct mapped<ranges::subrange<I, S, ranges::subrange_kind::sized>> {
// clang-format on
template <class>
using apply = ranges::subrange<I, S, ranges::subrange_kind::sized>;
};

template <ranges::viewable_range Rng>
using pipeline_t = mapped_t<mapped_t<mapped_t<mapped_t<views::all_t<Rng>>>>>;
using mapped_t = typename mapped<remove_cvref_t<Rng>>::template apply<Rng>;

template <ranges::viewable_range Rng>
using pipeline_t = mapped_t<mapped_t<mapped_t<mapped_t<Rng>>>>;

template <class Rng>
concept CanViewDrop = requires(Rng&& r) {
Expand All @@ -71,7 +88,7 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
constexpr bool is_view = ranges::view<remove_cvref_t<Rng>>;

using V = views::all_t<Rng>;
using M = mapped_t<V>;
using M = mapped_t<Rng>;
STATIC_ASSERT(ranges::view<M>);
STATIC_ASSERT(common_range<M> == common_range<Rng>);
STATIC_ASSERT(input_range<M> == input_range<Rng>);
Expand All @@ -81,7 +98,7 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
STATIC_ASSERT(contiguous_range<M> == contiguous_range<Rng>);

// Validate range adaptor object and range adaptor closure
constexpr auto drop_four = views::drop(4);
constexpr auto closure = views::drop(4);

// ... with lvalue argument
STATIC_ASSERT(CanViewDrop<Rng&> == (!is_view || copyable<V>) );
Expand All @@ -91,49 +108,49 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
STATIC_ASSERT(same_as<decltype(views::drop(rng, 4)), M>);
STATIC_ASSERT(noexcept(views::drop(rng, 4)) == is_noexcept);

STATIC_ASSERT(same_as<decltype(rng | drop_four), M>);
STATIC_ASSERT(noexcept(rng | drop_four) == is_noexcept);
STATIC_ASSERT(same_as<decltype(rng | closure), M>);
STATIC_ASSERT(noexcept(rng | closure) == is_noexcept);

STATIC_ASSERT(same_as<decltype(rng | pipeline), pipeline_t<Rng&>>);
STATIC_ASSERT(noexcept(rng | pipeline) == is_noexcept);
}

// ... with const lvalue argument
STATIC_ASSERT(CanViewDrop<const remove_reference_t<Rng>&> == (!is_view || copyable<V>) );
if constexpr (is_view && copyable<V>) {
if constexpr (is_span<remove_cvref_t<Rng>> || (is_view && copyable<V>) ) {
constexpr bool is_noexcept = (is_nothrow_copy_constructible_v<V> && !is_subrange<V>);

STATIC_ASSERT(same_as<decltype(views::drop(as_const(rng), 4)), M>);
STATIC_ASSERT(noexcept(views::drop(as_const(rng), 4)) == is_noexcept);

STATIC_ASSERT(same_as<decltype(as_const(rng) | drop_four), M>);
STATIC_ASSERT(noexcept(as_const(rng) | drop_four) == is_noexcept);
STATIC_ASSERT(same_as<decltype(as_const(rng) | closure), M>);
STATIC_ASSERT(noexcept(as_const(rng) | closure) == is_noexcept);

STATIC_ASSERT(same_as<decltype(as_const(rng) | pipeline), pipeline_t<const remove_reference_t<Rng>&>>);
STATIC_ASSERT(noexcept(as_const(rng) | pipeline) == is_noexcept);
} else if constexpr (!is_view) {
using RC = mapped_t<views::all_t<const remove_reference_t<Rng>&>>;
using RC = mapped_t<const remove_reference_t<Rng>&>;
constexpr bool is_noexcept = is_nothrow_constructible_v<RC, const remove_reference_t<Rng>&, int>;

STATIC_ASSERT(same_as<decltype(views::drop(as_const(rng), 4)), RC>);
STATIC_ASSERT(noexcept(views::drop(as_const(rng), 4)) == is_noexcept);

STATIC_ASSERT(same_as<decltype(as_const(rng) | drop_four), RC>);
STATIC_ASSERT(noexcept(as_const(rng) | drop_four) == is_noexcept);
STATIC_ASSERT(same_as<decltype(as_const(rng) | closure), RC>);
STATIC_ASSERT(noexcept(as_const(rng) | closure) == is_noexcept);

STATIC_ASSERT(same_as<decltype(as_const(rng) | pipeline), pipeline_t<const remove_reference_t<Rng>&>>);
STATIC_ASSERT(noexcept(as_const(rng) | pipeline) == is_noexcept);
}

// ... with rvalue argument
STATIC_ASSERT(CanViewDrop<remove_reference_t<Rng>> == is_view || enable_borrowed_range<remove_cvref_t<Rng>>);
if constexpr (is_view) {
if constexpr (is_span<remove_cvref_t<Rng>> || is_view) {
constexpr bool is_noexcept = is_nothrow_move_constructible_v<V> && !is_subrange<V>;
STATIC_ASSERT(same_as<decltype(views::drop(move(rng), 4)), M>);
STATIC_ASSERT(noexcept(views::drop(move(rng), 4)) == is_noexcept);

STATIC_ASSERT(same_as<decltype(move(rng) | drop_four), M>);
STATIC_ASSERT(noexcept(move(rng) | drop_four) == is_noexcept);
STATIC_ASSERT(same_as<decltype(move(rng) | closure), M>);
STATIC_ASSERT(noexcept(move(rng) | closure) == is_noexcept);

STATIC_ASSERT(same_as<decltype(move(rng) | pipeline), pipeline_t<remove_reference_t<Rng>>>);
STATIC_ASSERT(noexcept(move(rng) | pipeline) == is_noexcept);
Expand All @@ -145,8 +162,8 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
STATIC_ASSERT(same_as<decltype(views::drop(move(rng), 4)), RS>);
STATIC_ASSERT(noexcept(views::drop(move(rng), 4)) == is_noexcept);

STATIC_ASSERT(same_as<decltype(move(rng) | drop_four), RS>);
STATIC_ASSERT(noexcept(move(rng) | drop_four) == is_noexcept);
STATIC_ASSERT(same_as<decltype(move(rng) | closure), RS>);
STATIC_ASSERT(noexcept(move(rng) | closure) == is_noexcept);

STATIC_ASSERT(same_as<decltype(move(rng) | pipeline), mapped_t<mapped_t<mapped_t<RS>>>>);
STATIC_ASSERT(noexcept(move(rng) | pipeline) == is_noexcept);
Expand All @@ -155,14 +172,14 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
// ... with const rvalue argument
STATIC_ASSERT(CanViewDrop<const remove_reference_t<Rng>> == (is_view && copyable<V>)
|| (!is_view && enable_borrowed_range<remove_cvref_t<Rng>>) );
if constexpr (is_view && copyable<V>) {
if constexpr (is_span<remove_cvref_t<Rng>> || (is_view && copyable<V>) ) {
constexpr bool is_noexcept = is_nothrow_copy_constructible_v<V> && !is_subrange<V>;

STATIC_ASSERT(same_as<decltype(views::drop(move(as_const(rng)), 4)), M>);
STATIC_ASSERT(noexcept(views::drop(move(as_const(rng)), 4)) == is_noexcept);

STATIC_ASSERT(same_as<decltype(move(as_const(rng)) | drop_four), M>);
STATIC_ASSERT(noexcept(move(as_const(rng)) | drop_four) == is_noexcept);
STATIC_ASSERT(same_as<decltype(move(as_const(rng)) | closure), M>);
STATIC_ASSERT(noexcept(move(as_const(rng)) | closure) == is_noexcept);

STATIC_ASSERT(same_as<decltype(move(as_const(rng)) | pipeline), pipeline_t<const remove_reference_t<Rng>>>);
STATIC_ASSERT(noexcept(move(as_const(rng)) | pipeline) == is_noexcept);
Expand All @@ -174,8 +191,8 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
STATIC_ASSERT(same_as<decltype(views::drop(move(as_const(rng)), 4)), RS>);
STATIC_ASSERT(noexcept(views::drop(move(as_const(rng)), 4)) == is_noexcept);

STATIC_ASSERT(same_as<decltype(move(as_const(rng)) | drop_four), RS>);
STATIC_ASSERT(noexcept(move(as_const(rng)) | drop_four) == is_noexcept);
STATIC_ASSERT(same_as<decltype(move(as_const(rng)) | closure), RS>);
STATIC_ASSERT(noexcept(move(as_const(rng)) | closure) == is_noexcept);

STATIC_ASSERT(same_as<decltype(move(as_const(rng)) | pipeline), mapped_t<mapped_t<mapped_t<RS>>>>);
STATIC_ASSERT(noexcept(move(as_const(rng)) | pipeline) == is_noexcept);
Expand Down Expand Up @@ -455,9 +472,13 @@ int main() {
// Validate views
{ // ... copyable
// Test all of the "reconstructible range" types: span, empty_view, subrange, basic_string_view, iota_view
constexpr span<const int> s{some_ints};
STATIC_ASSERT(test_one(s, only_four_ints));
test_one(s, only_four_ints);
constexpr span s0{some_ints};
STATIC_ASSERT(test_one(s0, only_four_ints));
test_one(s0, only_four_ints);

constexpr span<const int> s1{some_ints};
STATIC_ASSERT(test_one(s1, only_four_ints));
test_one(s1, only_four_ints);

STATIC_ASSERT(test_one(ranges::subrange{some_ints}, only_four_ints));
test_one(ranges::subrange{some_ints}, only_four_ints);
Expand All @@ -468,9 +489,8 @@ int main() {
STATIC_ASSERT(test_one(basic_string_view{ranges::begin(some_ints), ranges::end(some_ints)}, only_four_ints));
test_one(basic_string_view{ranges::begin(some_ints), ranges::end(some_ints)}, only_four_ints);

// TRANSITION, iota_view
// STATIC_ASSERT(test_one(ranges::iota_view{0, 8}, only_four_ints));
// test_one(ranges::iota_view{0, 8}, only_four_ints);
STATIC_ASSERT(test_one(ranges::iota_view{0, 8}, only_four_ints));
test_one(ranges::iota_view{0, 8}, only_four_ints);
}
// ... move-only
STATIC_ASSERT((move_only_test(), true));
Expand All @@ -490,13 +510,6 @@ int main() {
test_one(lst, only_four_ints);
}

// Validate a non-view borrowed range
{
constexpr span s{some_ints};
STATIC_ASSERT(test_one(s, only_four_ints));
test_one(s, only_four_ints);
}

// Validate an output range
STATIC_ASSERT((output_range_test(), true));
output_range_test();
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0896R4_views_iota/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\strict_concepts_matrix.lst
Loading