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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 // UNSUPPORTED: libcpp-has-no-incomplete-ranges 11 12 // constexpr sentinel<false> end(); 13 // constexpr iterator<false> end() requires common_range<V>; 14 // constexpr sentinel<true> end() const 15 // requires range<const V> && 16 // regular_invocable<const F&, range_reference_t<const V>>; 17 // constexpr iterator<true> end() const 18 // requires common_range<const V> && 19 // regular_invocable<const F&, range_reference_t<const V>>; 20 21 #include <ranges> 22 23 #include "test_macros.h" 24 #include "types.h" 25 26 template<class T> 27 concept HasConstQualifiedEnd = requires(const T& t) { t.end(); }; 28 29 constexpr bool test() { 30 { 31 using TransformView = std::ranges::transform_view<ForwardView, PlusOneMutable>; 32 static_assert(std::ranges::common_range<TransformView>); 33 TransformView tv; 34 auto it = tv.end(); 35 using It = decltype(it); 36 ASSERT_SAME_TYPE(decltype(static_cast<It&>(it).base()), const forward_iterator<int*>&); 37 ASSERT_SAME_TYPE(decltype(static_cast<It&&>(it).base()), forward_iterator<int*>); 38 ASSERT_SAME_TYPE(decltype(static_cast<const It&>(it).base()), const forward_iterator<int*>&); 39 ASSERT_SAME_TYPE(decltype(static_cast<const It&&>(it).base()), const forward_iterator<int*>&); 40 assert(base(it.base()) == globalBuff + 8); 41 assert(base(std::move(it).base()) == globalBuff + 8); 42 static_assert(!HasConstQualifiedEnd<TransformView>); 43 } 44 { 45 using TransformView = std::ranges::transform_view<InputView, PlusOneMutable>; 46 static_assert(!std::ranges::common_range<TransformView>); 47 TransformView tv; 48 auto sent = tv.end(); 49 using Sent = decltype(sent); 50 ASSERT_SAME_TYPE(decltype(static_cast<Sent&>(sent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 51 ASSERT_SAME_TYPE(decltype(static_cast<Sent&&>(sent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 52 ASSERT_SAME_TYPE(decltype(static_cast<const Sent&>(sent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 53 ASSERT_SAME_TYPE(decltype(static_cast<const Sent&&>(sent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 54 assert(base(base(sent.base())) == globalBuff + 8); 55 assert(base(base(std::move(sent).base())) == globalBuff + 8); 56 static_assert(!HasConstQualifiedEnd<TransformView>); 57 } 58 { 59 using TransformView = std::ranges::transform_view<InputView, PlusOne>; 60 static_assert(!std::ranges::common_range<TransformView>); 61 TransformView tv; 62 auto sent = tv.end(); 63 using Sent = decltype(sent); 64 ASSERT_SAME_TYPE(decltype(static_cast<Sent&>(sent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 65 ASSERT_SAME_TYPE(decltype(static_cast<Sent&&>(sent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 66 ASSERT_SAME_TYPE(decltype(static_cast<const Sent&>(sent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 67 ASSERT_SAME_TYPE(decltype(static_cast<const Sent&&>(sent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 68 assert(base(base(sent.base())) == globalBuff + 8); 69 assert(base(base(std::move(sent).base())) == globalBuff + 8); 70 71 auto csent = std::as_const(tv).end(); 72 using CSent = decltype(csent); 73 ASSERT_SAME_TYPE(decltype(static_cast<CSent&>(csent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 74 ASSERT_SAME_TYPE(decltype(static_cast<CSent&&>(csent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 75 ASSERT_SAME_TYPE(decltype(static_cast<const CSent&>(csent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 76 ASSERT_SAME_TYPE(decltype(static_cast<const CSent&&>(csent).base()), sentinel_wrapper<cpp20_input_iterator<int*>>); 77 assert(base(base(csent.base())) == globalBuff + 8); 78 assert(base(base(std::move(csent).base())) == globalBuff + 8); 79 } 80 { 81 using TransformView = std::ranges::transform_view<MoveOnlyView, PlusOneMutable>; 82 static_assert(std::ranges::common_range<TransformView>); 83 TransformView tv; 84 auto it = tv.end(); 85 using It = decltype(it); 86 ASSERT_SAME_TYPE(decltype(static_cast<It&>(it).base()), int* const&); 87 ASSERT_SAME_TYPE(decltype(static_cast<It&&>(it).base()), int*); 88 ASSERT_SAME_TYPE(decltype(static_cast<const It&>(it).base()), int* const&); 89 ASSERT_SAME_TYPE(decltype(static_cast<const It&&>(it).base()), int* const&); 90 assert(base(it.base()) == globalBuff + 8); 91 assert(base(std::move(it).base()) == globalBuff + 8); 92 static_assert(!HasConstQualifiedEnd<TransformView>); 93 } 94 { 95 using TransformView = std::ranges::transform_view<MoveOnlyView, PlusOne>; 96 static_assert(std::ranges::common_range<TransformView>); 97 TransformView tv; 98 auto it = tv.end(); 99 using It = decltype(it); 100 ASSERT_SAME_TYPE(decltype(static_cast<It&>(it).base()), int* const&); 101 ASSERT_SAME_TYPE(decltype(static_cast<It&&>(it).base()), int*); 102 ASSERT_SAME_TYPE(decltype(static_cast<const It&>(it).base()), int* const&); 103 ASSERT_SAME_TYPE(decltype(static_cast<const It&&>(it).base()), int* const&); 104 assert(base(it.base()) == globalBuff + 8); 105 assert(base(std::move(it).base()) == globalBuff + 8); 106 107 auto csent = std::as_const(tv).end(); 108 using CSent = decltype(csent); 109 ASSERT_SAME_TYPE(decltype(static_cast<CSent&>(csent).base()), int* const&); 110 ASSERT_SAME_TYPE(decltype(static_cast<CSent&&>(csent).base()), int*); 111 ASSERT_SAME_TYPE(decltype(static_cast<const CSent&>(csent).base()), int* const&); 112 ASSERT_SAME_TYPE(decltype(static_cast<const CSent&&>(csent).base()), int* const&); 113 assert(base(base(csent.base())) == globalBuff + 8); 114 assert(base(base(std::move(csent).base())) == globalBuff + 8); 115 } 116 return true; 117 } 118 119 int main(int, char**) { 120 test(); 121 static_assert(test()); 122 123 return 0; 124 } 125