205 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// std::views::all;12 13#include <ranges>14 15#include <cassert>16#include <concepts>17#include <type_traits>18#include <utility>19 20#include "test_iterators.h"21#include "test_macros.h"22#include "test_range.h"23 24int globalBuff[8];25 26template<bool IsNoexcept>27struct View : std::ranges::view_base {28 int start_ = 0;29 explicit View() noexcept(IsNoexcept) = default;30 constexpr explicit View(int start) : start_(start) {}31 View(View&&) noexcept(IsNoexcept) = default;32 View& operator=(View&&) noexcept(IsNoexcept) = default;33 constexpr int* begin() const { return globalBuff + start_; }34 constexpr int* end() const { return globalBuff + 8; }35};36static_assert(std::ranges::view<View<true>>);37static_assert(std::ranges::view<View<false>>);38 39template<bool IsNoexcept>40struct CopyableView : std::ranges::view_base {41 int start_ = 0;42 explicit CopyableView() noexcept(IsNoexcept) = default;43 CopyableView(CopyableView const&) noexcept(IsNoexcept) = default;44 CopyableView& operator=(CopyableView const&) noexcept(IsNoexcept) = default;45 constexpr explicit CopyableView(int start) noexcept : start_(start) {}46 constexpr int* begin() const { return globalBuff + start_; }47 constexpr int* end() const { return globalBuff + 8; }48};49static_assert(std::ranges::view<CopyableView<true>>);50static_assert(std::ranges::view<CopyableView<false>>);51 52struct MoveOnlyView : std::ranges::view_base{53 MoveOnlyView() = default;54 MoveOnlyView(const MoveOnlyView&) = delete;55 MoveOnlyView& operator=(const MoveOnlyView&) = delete;56 MoveOnlyView(MoveOnlyView&&) = default;57 MoveOnlyView& operator=(MoveOnlyView&&) = default;58 59 int* begin() const;60 int* end() const;61};62 63struct Range {64 int start_;65 constexpr explicit Range(int start) noexcept : start_(start) {}66 constexpr int* begin() const { return globalBuff + start_; }67 constexpr int* end() const { return globalBuff + 8; }68};69 70struct BorrowableRange {71 int start_;72 constexpr explicit BorrowableRange(int start) noexcept : start_(start) {}73 constexpr int* begin() const { return globalBuff + start_; }74 constexpr int* end() const { return globalBuff + 8; }75};76template<>77inline constexpr bool std::ranges::enable_borrowed_range<BorrowableRange> = true;78 79struct RandomAccessRange {80 constexpr auto begin() { return random_access_iterator<int*>(globalBuff); }81 constexpr auto end() { return sized_sentinel(random_access_iterator<int*>(globalBuff + 8)); }82};83template<>84inline constexpr bool std::ranges::enable_borrowed_range<RandomAccessRange> = true;85 86constexpr bool test() {87 {88 ASSERT_SAME_TYPE(decltype(std::views::all(View<true>())), View<true>);89 static_assert(noexcept(std::views::all(View<true>())));90 static_assert(!noexcept(std::views::all(View<false>())));91 92 auto viewCopy = std::views::all(View<true>(2));93 ASSERT_SAME_TYPE(decltype(viewCopy), View<true>);94 assert(std::ranges::begin(viewCopy) == globalBuff + 2);95 assert(std::ranges::end(viewCopy) == globalBuff + 8);96 }97 98 {99 ASSERT_SAME_TYPE(decltype(std::views::all(std::declval<const CopyableView<true>&>())), CopyableView<true>);100 static_assert(noexcept(std::views::all(CopyableView<true>())));101 static_assert(!noexcept(std::views::all(CopyableView<false>())));102 103 CopyableView<true> view(2);104 auto viewCopy = std::views::all(view);105 ASSERT_SAME_TYPE(decltype(viewCopy), CopyableView<true>);106 assert(std::ranges::begin(viewCopy) == globalBuff + 2);107 assert(std::ranges::end(viewCopy) == globalBuff + 8);108 }109 110 {111 Range range(2);112 auto ref = std::views::all(range);113 ASSERT_SAME_TYPE(decltype(ref), std::ranges::ref_view<Range>);114 assert(std::ranges::begin(ref) == globalBuff + 2);115 assert(std::ranges::end(ref) == globalBuff + 8);116 117 auto own = std::views::all(std::move(range));118 ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view<Range>);119 assert(std::ranges::begin(own) == globalBuff + 2);120 assert(std::ranges::end(own) == globalBuff + 8);121 122 auto cref = std::views::all(std::as_const(range));123 ASSERT_SAME_TYPE(decltype(cref), std::ranges::ref_view<const Range>);124 assert(std::ranges::begin(cref) == globalBuff + 2);125 assert(std::ranges::end(cref) == globalBuff + 8);126 127 static_assert(!std::is_invocable_v<decltype(std::views::all), const Range&&>);128 }129 130 {131 auto own = std::views::all(BorrowableRange(2));132 ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view<BorrowableRange>);133 assert(std::ranges::begin(own) == globalBuff + 2);134 assert(std::ranges::end(own) == globalBuff + 8);135 }136 137 {138 auto own = std::views::all(RandomAccessRange());139 ASSERT_SAME_TYPE(decltype(own), std::ranges::owning_view<RandomAccessRange>);140 assert(base(std::ranges::begin(own)) == globalBuff);141 assert(base(base(std::ranges::end(own))) == globalBuff + 8);142 }143 144 // Check SFINAE friendliness of the call operator145 {146 static_assert(!std::is_invocable_v<decltype(std::views::all)>);147 static_assert(!std::is_invocable_v<decltype(std::views::all), RandomAccessRange, RandomAccessRange>);148 149 // `views::all(v)` is expression equivalent to `decay-copy(v)` if the decayed type150 // of `v` models `view`. If `v` is an lvalue-reference to a move-only view, the151 // expression should be ill-formed because `v` is not copyable152 static_assert(!std::is_invocable_v<decltype(std::views::all), MoveOnlyView&>);153 }154 155 // Test that std::views::all is a range adaptor156 {157 // Test `v | views::all`158 {159 Range range(0);160 auto result = range | std::views::all;161 ASSERT_SAME_TYPE(decltype(result), std::ranges::ref_view<Range>);162 assert(&result.base() == &range);163 }164 165 // Test `adaptor | views::all`166 {167 Range range(0);168 auto f = [](int i) { return i; };169 auto const partial = std::views::transform(f) | std::views::all;170 using Result = std::ranges::transform_view<std::ranges::ref_view<Range>, decltype(f)>;171 std::same_as<Result> auto result = partial(range);172 assert(&result.base().base() == &range);173 }174 175 // Test `views::all | adaptor`176 {177 Range range(0);178 auto f = [](int i) { return i; };179 auto const partial = std::views::all | std::views::transform(f);180 using Result = std::ranges::transform_view<std::ranges::ref_view<Range>, decltype(f)>;181 std::same_as<Result> auto result = partial(range);182 assert(&result.base().base() == &range);183 }184 185 {186 struct NotAView { };187 static_assert( CanBePiped<Range&, decltype(std::views::all)>);188 static_assert(!CanBePiped<NotAView, decltype(std::views::all)>);189 }190 }191 192 {193 static_assert(std::same_as<decltype(std::views::all), decltype(std::ranges::views::all)>);194 }195 196 return true;197}198 199int main(int, char**) {200 test();201 static_assert(test());202 203 return 0;204}205