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: gcc-10 12 // UNSUPPORTED: libcpp-has-no-incomplete-ranges 13 14 // template<class R> 15 // concept viewable_range; 16 17 #include <ranges> 18 #include <type_traits> 19 20 #include "test_iterators.h" 21 #include "test_range.h" 22 23 // The constraints we have in viewable_range are: 24 // range<T> 25 // view<remove_cvref_t<T>> 26 // constructible_from<remove_cvref_t<T>, T> 27 // borrowed_range<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=*, borrowed_range=*) 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 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, borrowed_range=true) 41 struct T2 : test_range<cpp20_input_iterator>, std::ranges::view_base { 42 T2(T2 const&) = default; 43 }; 44 template<> constexpr bool std::ranges::enable_borrowed_range<T2> = true; 45 static_assert(std::ranges::range<T2>); 46 static_assert(std::ranges::view<T2>); 47 static_assert(std::constructible_from<T2, T2>); 48 static_assert(std::ranges::borrowed_range<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 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, borrowed_range=false) 56 struct T3 : test_range<cpp20_input_iterator>, std::ranges::view_base { 57 T3(T3 const&) = default; 58 }; 59 template<> constexpr bool std::ranges::enable_borrowed_range<T3> = false; 60 static_assert(std::ranges::range<T3>); 61 static_assert(std::ranges::view<T3>); 62 static_assert(std::constructible_from<T3, T3>); 63 static_assert(!std::ranges::borrowed_range<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 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, borrowed_range=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 static_assert(std::ranges::borrowed_range<T4 const&>); 80 81 static_assert(!std::ranges::viewable_range<T4 const&>); 82 83 // A type that satisfies (range=true, view=true, constructible_from=false, borrowed_range=false) can't be formed 84 85 // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=true, borrowed_range=true) 86 struct T5 : test_range<cpp20_input_iterator> { }; 87 template<> constexpr bool std::ranges::enable_borrowed_range<T5> = true; 88 static_assert(std::ranges::range<T5>); 89 static_assert(!std::ranges::view<T5>); 90 static_assert(std::constructible_from<T5, T5>); 91 static_assert(std::ranges::borrowed_range<T5>); 92 93 static_assert(std::ranges::viewable_range<T5>); 94 95 // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, borrowed_range=false) 96 struct T6 : test_range<cpp20_input_iterator> { }; 97 template<> constexpr bool std::ranges::enable_borrowed_range<T6> = false; 98 static_assert(std::ranges::range<T6>); 99 static_assert(!std::ranges::view<T6>); 100 static_assert(std::constructible_from<T6, T6>); 101 static_assert(!std::ranges::borrowed_range<T6>); 102 103 static_assert(!std::ranges::viewable_range<T6>); 104 105 // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=false, borrowed_range=true) 106 struct T7 : test_range<cpp20_input_iterator> { 107 T7(T7 const&) = delete; 108 }; 109 static_assert(std::ranges::range<T7&>); 110 static_assert(!std::ranges::view<std::remove_cvref_t<T7&>>); 111 static_assert(!std::constructible_from<std::remove_cvref_t<T7&>, T7&>); 112 static_assert(std::ranges::borrowed_range<T7&>); 113 114 static_assert(std::ranges::viewable_range<T7&>); 115 116 // A type that satisfies (range=true, view=false, constructible_from=false, borrowed_range=false) can't be formed 117 struct T8 : test_range<cpp20_input_iterator> { 118 T8(T8 const&) = delete; 119 }; 120 static_assert(std::ranges::range<T8>); 121 static_assert(!std::ranges::view<T8>); 122 static_assert(!std::constructible_from<T8, T8>); 123 static_assert(!std::ranges::borrowed_range<T8>); 124 125 static_assert(!std::ranges::viewable_range<T8>); 126 127 // Test with a few degenerate types 128 static_assert(!std::ranges::viewable_range<void>); 129 static_assert(!std::ranges::viewable_range<int>); 130 static_assert(!std::ranges::viewable_range<int (*)(char)>); 131 static_assert(!std::ranges::viewable_range<int[]>); 132 static_assert(!std::ranges::viewable_range<int[10]>); 133 static_assert(!std::ranges::viewable_range<int(&)[]>); // unbounded array is not a range 134 static_assert( std::ranges::viewable_range<int(&)[10]>); 135