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 auto begin(); 13 // constexpr auto begin() const 14 // requires input_range<const V> && 15 // is_reference_v<range_reference_t<const V>>; 16 17 #include <cassert> 18 #include <ranges> 19 20 #include "types.h" 21 22 struct NonSimpleParentView : std::ranges::view_base { 23 ChildView* begin() { return nullptr; } 24 const ChildView* begin() const; 25 const ChildView* end() const; 26 }; 27 28 struct SimpleParentView : std::ranges::view_base { 29 const ChildView* begin() const; 30 const ChildView* end() const; 31 }; 32 33 struct ConstNotRange : std::ranges::view_base { 34 const ChildView* begin(); 35 const ChildView* end(); 36 }; 37 static_assert(std::ranges::range<ConstNotRange>); 38 static_assert(!std::ranges::range<const ConstNotRange>); 39 40 template <class T> 41 concept HasConstBegin = requires(const T& t) { t.begin(); }; 42 43 constexpr bool test() { 44 int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}}; 45 46 { 47 ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])}; 48 auto jv = std::ranges::join_view(ParentView{children}); 49 assert(*jv.begin() == 1111); 50 } 51 52 { 53 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 1), 54 CopyableChild(buffer[3], 0)}; 55 auto jv = std::ranges::join_view(ParentView{children}); 56 assert(*jv.begin() == 1111); 57 } 58 59 // Parent is empty. 60 { 61 CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), 62 CopyableChild(buffer[3])}; 63 std::ranges::join_view jv(ParentView(children, 0)); 64 assert(jv.begin() == jv.end()); 65 } 66 67 // Parent size is one. 68 { 69 CopyableChild children[1] = {CopyableChild(buffer[0])}; 70 std::ranges::join_view jv(ParentView(children, 1)); 71 assert(*jv.begin() == 1111); 72 } 73 74 // Parent and child size is one. 75 { 76 CopyableChild children[1] = {CopyableChild(buffer[0], 1)}; 77 std::ranges::join_view jv(ParentView(children, 1)); 78 assert(*jv.begin() == 1111); 79 } 80 81 // Parent size is one child is empty 82 { 83 CopyableChild children[1] = {CopyableChild(buffer[0], 0)}; 84 std::ranges::join_view jv(ParentView(children, 1)); 85 assert(jv.begin() == jv.end()); 86 } 87 88 // Has all empty children. 89 { 90 CopyableChild children[4] = {CopyableChild(buffer[0], 0), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0), 91 CopyableChild(buffer[3], 0)}; 92 auto jv = std::ranges::join_view(ParentView{children}); 93 assert(jv.begin() == jv.end()); 94 } 95 96 // First child is empty, others are not. 97 { 98 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 0), CopyableChild(buffer[2], 0), 99 CopyableChild(buffer[3], 0)}; 100 auto jv = std::ranges::join_view(ParentView{children}); 101 assert(*jv.begin() == 1111); 102 } 103 104 // Last child is empty, others are not. 105 { 106 CopyableChild children[4] = {CopyableChild(buffer[0], 4), CopyableChild(buffer[1], 4), CopyableChild(buffer[2], 4), 107 CopyableChild(buffer[3], 0)}; 108 auto jv = std::ranges::join_view(ParentView{children}); 109 assert(*jv.begin() == 1111); 110 } 111 112 { 113 std::ranges::join_view jv(buffer); 114 assert(*jv.begin() == 1111); 115 } 116 117 { 118 const std::ranges::join_view jv(buffer); 119 assert(*jv.begin() == 1111); 120 static_assert(HasConstBegin<decltype(jv)>); 121 } 122 123 // !input_range<const V> 124 { 125 std::ranges::join_view jv{ConstNotRange{}}; 126 static_assert(!HasConstBegin<decltype(jv)>); 127 } 128 129 // !is_reference_v<range_reference_t<const V>> 130 { 131 auto innerRValueRange = std::views::iota(0, 5) | std::views::transform([](int) { return ChildView{}; }); 132 static_assert(!std::is_reference_v<std::ranges::range_reference_t<const decltype(innerRValueRange)>>); 133 std::ranges::join_view jv{innerRValueRange}; 134 static_assert(!HasConstBegin<decltype(jv)>); 135 } 136 137 // !simple-view<V> 138 { 139 std::ranges::join_view<NonSimpleParentView> jv; 140 static_assert(!std::same_as<decltype(jv.begin()), decltype(std::as_const(jv).begin())>); 141 } 142 143 // simple-view<V> && is_reference_v<range_reference_t<V>>; 144 { 145 std::ranges::join_view<SimpleParentView> jv; 146 static_assert(std::same_as<decltype(jv.begin()), decltype(std::as_const(jv).begin())>); 147 } 148 149 return true; 150 } 151 152 int main(int, char**) { 153 test(); 154 static_assert(test()); 155 156 return 0; 157 } 158