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 11 // template<class R> 12 // concept viewable_range; 13 14 #include <ranges> 15 #include <type_traits> 16 17 #include "test_iterators.h" 18 #include "test_range.h" 19 20 // The constraints we have in viewable_range are: 21 // range<T> 22 // view<remove_cvref_t<T>> 23 // constructible_from<remove_cvref_t<T>, T> 24 // lvalue_reference_t<T> || movable<remove_reference_t<T>> 25 // is-initializer-list<T> 26 // 27 // We test all the relevant combinations of satisfying/not satisfying those constraints. 28 29 // viewable_range<T> is not satisfied for (range=false, view=*, constructible_from=*, lvalue-or-movable=*) 30 struct T1 { }; 31 static_assert(!std::ranges::range<T1>); 32 33 static_assert(!std::ranges::viewable_range<T1>); 34 static_assert(!std::ranges::viewable_range<T1&>); 35 static_assert(!std::ranges::viewable_range<T1&&>); 36 static_assert(!std::ranges::viewable_range<T1 const>); 37 static_assert(!std::ranges::viewable_range<T1 const&>); 38 static_assert(!std::ranges::viewable_range<T1 const&&>); 39 40 // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, lvalue-or-movable=true) 41 struct T2 : test_range<cpp20_input_iterator>, std::ranges::view_base { 42 T2(T2 const&) = default; 43 }; 44 static_assert(std::ranges::range<T2>); 45 static_assert(std::ranges::view<T2>); 46 static_assert(std::constructible_from<T2, T2>); 47 48 static_assert(std::ranges::viewable_range<T2>); 49 static_assert(std::ranges::viewable_range<T2&>); 50 static_assert(std::ranges::viewable_range<T2&&>); 51 static_assert(std::ranges::viewable_range<T2 const>); 52 static_assert(std::ranges::viewable_range<T2 const&>); 53 static_assert(std::ranges::viewable_range<T2 const&&>); 54 55 // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, lvalue-or-movable=false) 56 struct T3 : test_range<cpp20_input_iterator>, std::ranges::view_base { 57 T3(T3 const&) = default; 58 }; 59 static_assert(std::ranges::range<T3>); 60 static_assert(std::ranges::view<T3>); 61 static_assert(std::constructible_from<T3, T3>); 62 63 static_assert(std::ranges::viewable_range<T3>); 64 static_assert(std::ranges::viewable_range<T3&>); 65 static_assert(std::ranges::viewable_range<T3&&>); 66 static_assert(std::ranges::viewable_range<T3 const>); 67 static_assert(std::ranges::viewable_range<T3 const&>); 68 static_assert(std::ranges::viewable_range<T3 const&&>); 69 70 // viewable_range<T> is not satisfied for (range=true, view=true, constructible_from=false, lvalue-or-movable=true) 71 struct T4 : test_range<cpp20_input_iterator>, std::ranges::view_base { 72 T4(T4 const&) = delete; 73 T4(T4&&) = default; // necessary to model view 74 T4& operator=(T4&&) = default; // necessary to model view 75 }; 76 static_assert(std::ranges::range<T4 const&>); 77 static_assert(std::ranges::view<std::remove_cvref_t<T4 const&>>); 78 static_assert(!std::constructible_from<std::remove_cvref_t<T4 const&>, T4 const&>); 79 80 static_assert(!std::ranges::viewable_range<T4 const&>); 81 82 // A type that satisfies (range=true, view=true, constructible_from=false, lvalue-or-movable=false) can't be formed, 83 // because views are movable by definition 84 85 // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=true, lvalue-or-movable=true)... 86 struct T5 : test_range<cpp20_input_iterator> { }; 87 static_assert( std::ranges::range<T5>); 88 static_assert(!std::ranges::view<T5>); 89 static_assert( std::constructible_from<T5, T5>); 90 static_assert( std::movable<T5>); 91 static_assert(!std::movable<const T5>); 92 93 static_assert( std::ranges::viewable_range<T5>); // movable 94 static_assert( std::ranges::viewable_range<T5&>); // movable 95 static_assert( std::ranges::viewable_range<T5&&>); // movable 96 static_assert(!std::ranges::viewable_range<const T5>); 97 static_assert( std::ranges::viewable_range<const T5&>); // lvalue 98 static_assert(!std::ranges::viewable_range<const T5&&>); 99 100 // ...but not if the (non-view, lvalue-or-movable) range is an initializer_list. 101 static_assert( std::ranges::range<std::initializer_list<int>>); 102 static_assert(!std::ranges::view<std::initializer_list<int>>); 103 static_assert( std::constructible_from<std::initializer_list<int>, std::initializer_list<int>>); 104 static_assert( std::movable<std::initializer_list<int>>); 105 106 static_assert(!std::ranges::viewable_range<std::initializer_list<int>>); 107 static_assert( std::ranges::viewable_range<std::initializer_list<int>&>); 108 static_assert(!std::ranges::viewable_range<std::initializer_list<int>&&>); 109 static_assert(!std::ranges::viewable_range<std::initializer_list<int> const>); 110 static_assert( std::ranges::viewable_range<std::initializer_list<int> const&>); 111 static_assert(!std::ranges::viewable_range<std::initializer_list<int> const&&>); 112 113 // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, lvalue-or-movable=false) 114 struct T6 : test_range<cpp20_input_iterator> { T6(T6&&); T6& operator=(T6&&) = delete; }; 115 static_assert( std::ranges::range<T6>); 116 static_assert(!std::ranges::view<T6>); 117 static_assert( std::constructible_from<T6, T6>); 118 static_assert(!std::movable<T6>); 119 120 static_assert(!std::ranges::viewable_range<T6>); 121 static_assert( std::ranges::viewable_range<T6&>); // lvalue 122 static_assert(!std::ranges::viewable_range<T6&&>); 123 static_assert(!std::ranges::viewable_range<const T6>); 124 static_assert( std::ranges::viewable_range<const T6&>); // lvalue 125 static_assert(!std::ranges::viewable_range<const T6&&>); 126 127 // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=false, lvalue-or-movable=true) 128 struct T7 : test_range<cpp20_input_iterator> { 129 T7(T7 const&) = delete; 130 }; 131 static_assert(std::ranges::range<T7&>); 132 static_assert(!std::ranges::view<std::remove_cvref_t<T7&>>); 133 static_assert(!std::constructible_from<std::remove_cvref_t<T7&>, T7&>); 134 135 static_assert(!std::ranges::viewable_range<T7>); 136 static_assert( std::ranges::viewable_range<T7&>); 137 static_assert(!std::ranges::viewable_range<T7&&>); 138 static_assert(!std::ranges::viewable_range<const T7>); 139 static_assert( std::ranges::viewable_range<const T7&>); 140 static_assert(!std::ranges::viewable_range<const T7&&>); 141 142 // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=false, lvalue-or-movable=false) 143 struct T8 : test_range<cpp20_input_iterator> { 144 T8(T8 const&) = delete; 145 }; 146 static_assert(std::ranges::range<T8>); 147 static_assert(!std::ranges::view<T8>); 148 static_assert(!std::constructible_from<T8, T8>); 149 150 static_assert(!std::ranges::viewable_range<T8>); 151 static_assert( std::ranges::viewable_range<T8&>); 152 static_assert(!std::ranges::viewable_range<T8&&>); 153 static_assert(!std::ranges::viewable_range<const T8>); 154 static_assert( std::ranges::viewable_range<const T8&>); 155 static_assert(!std::ranges::viewable_range<const T8&&>); 156 157 // Test with a few degenerate types 158 static_assert(!std::ranges::viewable_range<void>); 159 static_assert(!std::ranges::viewable_range<int>); 160 static_assert(!std::ranges::viewable_range<int (*)(char)>); 161 static_assert(!std::ranges::viewable_range<int[]>); 162 static_assert(!std::ranges::viewable_range<int[10]>); 163 static_assert(!std::ranges::viewable_range<int(&)[]>); // not a range 164 static_assert( std::ranges::viewable_range<int(&)[10]>); // OK, lvalue 165 static_assert(!std::ranges::viewable_range<int(&&)[]>); 166 static_assert(!std::ranges::viewable_range<int(&&)[10]>); 167 168 // Test ADL-proofing. 169 struct Incomplete; 170 template<class T> struct Holder { T t; }; 171 172 static_assert(!std::ranges::viewable_range<Holder<Incomplete>*>); 173 static_assert(!std::ranges::viewable_range<Holder<Incomplete>*&>); 174 static_assert(!std::ranges::viewable_range<Holder<Incomplete>*&&>); 175 static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const>); 176 static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const&>); 177 static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const&&>); 178 179 static_assert(!std::ranges::viewable_range<Holder<Incomplete>*[10]>); 180 static_assert( std::ranges::viewable_range<Holder<Incomplete>*(&)[10]>); 181 static_assert(!std::ranges::viewable_range<Holder<Incomplete>*(&&)[10]>); 182 static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const[10]>); 183 static_assert( std::ranges::viewable_range<Holder<Incomplete>* const(&)[10]>); 184 static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const(&&)[10]>); 185