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