162 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// constexpr auto begin()12// requires (!(simple-view<V> &&13// random_access_range<const V> && sized_range<const V>));14// constexpr auto begin() const15// requires random_access_range<const V> && sized_range<const V>;16 17#include <ranges>18 19#include "test_macros.h"20#include "test_iterators.h"21#include "test_range.h"22#include "types.h"23 24template<class T>25concept BeginInvocable = requires(std::ranges::drop_view<T> t) { t.begin(); };26 27template <bool IsSimple>28struct MaybeSimpleView : std::ranges::view_base {29 int* num_of_non_const_begin_calls;30 int* num_of_const_begin_calls;31 32 constexpr int* begin() {33 ++(*num_of_non_const_begin_calls);34 return nullptr;35 }36 constexpr std::conditional_t<IsSimple, int*, const int*> begin() const {37 ++(*num_of_const_begin_calls);38 return nullptr;39 }40 constexpr int* end() const { return nullptr; }41 constexpr std::size_t size() const { return 0; }42};43 44using SimpleView = MaybeSimpleView<true>;45using NonSimpleView = MaybeSimpleView<false>;46 47constexpr bool test() {48 // random_access_range<const V> && sized_range<const V>49 std::ranges::drop_view dropView1(MoveOnlyView(), 4);50 assert(dropView1.begin() == globalBuff + 4);51 52 // !random_access_range<const V>53 std::ranges::drop_view dropView2(ForwardView(), 4);54 assert(base(dropView2.begin()) == globalBuff + 4);55 56 // !random_access_range<const V>57 std::ranges::drop_view dropView3(InputView(), 4);58 assert(base(dropView3.begin()) == globalBuff + 4);59 60 // random_access_range<const V> && sized_range<const V>61 std::ranges::drop_view dropView4(MoveOnlyView(), 8);62 assert(dropView4.begin() == globalBuff + 8);63 64 // random_access_range<const V> && sized_range<const V>65 std::ranges::drop_view dropView5(MoveOnlyView(), 0);66 assert(dropView5.begin() == globalBuff);67 68 // random_access_range<const V> && sized_range<const V>69 const std::ranges::drop_view dropView6(MoveOnlyView(), 0);70 assert(dropView6.begin() == globalBuff);71 72 // random_access_range<const V> && sized_range<const V>73 std::ranges::drop_view dropView7(MoveOnlyView(), 10);74 assert(dropView7.begin() == globalBuff + 8);75 76 IteratorOpCounts opcounts;77 CountedView view8(&opcounts);78 ;79 std::ranges::drop_view dropView8(view8, 5);80 assert(base(base(dropView8.begin())) == globalBuff + 5);81 assert(opcounts.increments == 5);82 83 static_assert(!BeginInvocable<const ForwardView>);84 85 {86 // non-common non-simple view,87 // The wording of the standard is:88 // Returns: ranges::next(ranges::begin(base_), count_, ranges::end(base_))89 // Note that "Returns" is used here, meaning that we don't have to do it this way.90 // In fact, this will use ranges::advance that has O(n) on non-common range.91 // but [range.range] requires "amortized constant time" for ranges::begin and ranges::end92 // Here, we test that begin() is indeed constant time, by creating a customized93 // sentinel and counting how many times the sentinel eq function is called.94 // It should be 0 times, but since this test (or any test under libcxx/test/std) is95 // also used by other implementations, we relax the condition to that96 // sentinel_cmp_calls is a constant number.97 int sentinel_cmp_calls_1 = 0;98 int sentinel_cmp_calls_2 = 0;99 using NonCommonView = MaybeSimpleNonCommonView<false>;100 static_assert(std::ranges::random_access_range<NonCommonView>);101 static_assert(std::ranges::sized_range<NonCommonView>);102 std::ranges::drop_view dropView9_1(NonCommonView{{}, 0, &sentinel_cmp_calls_1}, 4);103 std::ranges::drop_view dropView9_2(NonCommonView{{}, 0, &sentinel_cmp_calls_2}, 6);104 assert(dropView9_1.begin() == globalBuff + 4);105 assert(dropView9_2.begin() == globalBuff + 6);106 assert(sentinel_cmp_calls_1 == sentinel_cmp_calls_2);107 }108 109 {110 // non-common simple view, same as above.111 int sentinel_cmp_calls_1 = 0;112 int sentinel_cmp_calls_2 = 0;113 using NonCommonView = MaybeSimpleNonCommonView<true>;114 static_assert(std::ranges::random_access_range<NonCommonView>);115 static_assert(std::ranges::sized_range<NonCommonView>);116 std::ranges::drop_view dropView10_1(NonCommonView{{}, 0, &sentinel_cmp_calls_1}, 4);117 std::ranges::drop_view dropView10_2(NonCommonView{{}, 0, &sentinel_cmp_calls_2}, 6);118 assert(dropView10_1.begin() == globalBuff + 4);119 assert(dropView10_2.begin() == globalBuff + 6);120 assert(sentinel_cmp_calls_1 == sentinel_cmp_calls_2);121 }122 123 {124 static_assert(std::ranges::random_access_range<const SimpleView>);125 static_assert(std::ranges::sized_range<const SimpleView>);126 static_assert(simple_view<SimpleView>);127 int non_const_calls = 0;128 int const_calls = 0;129 std::ranges::drop_view dropView(SimpleView{{}, &non_const_calls, &const_calls}, 4);130 assert(dropView.begin() == nullptr);131 assert(non_const_calls == 0);132 assert(const_calls == 1);133 assert(std::as_const(dropView).begin() == nullptr);134 assert(non_const_calls == 0);135 assert(const_calls == 2);136 }137 138 {139 static_assert(std::ranges::random_access_range<const NonSimpleView>);140 static_assert(std::ranges::sized_range<const NonSimpleView>);141 static_assert(!simple_view<NonSimpleView>);142 int non_const_calls = 0;143 int const_calls = 0;144 std::ranges::drop_view dropView(NonSimpleView{{}, &non_const_calls, &const_calls}, 4);145 assert(dropView.begin() == nullptr);146 assert(non_const_calls == 1);147 assert(const_calls == 0);148 assert(std::as_const(dropView).begin() == nullptr);149 assert(non_const_calls == 1);150 assert(const_calls == 1);151 }152 153 return true;154}155 156int main(int, char**) {157 test();158 static_assert(test());159 160 return 0;161}162