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 // borrowed_range<T> 27 // 28 // We test all the relevant combinations of satisfying/not satisfying those constraints. 29 30 // viewable_range<T> is not satisfied for (range=false, view=*, constructible_from=*, borrowed_range=*) 31 struct T1 { }; 32 static_assert(!std::ranges::range<T1>); 33 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 39 // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=true) 40 struct T2 : test_range<cpp20_input_iterator>, std::ranges::view_base { 41 T2(T2 const&) = default; 42 }; 43 template<> constexpr bool std::ranges::enable_borrowed_range<T2> = true; 44 static_assert(std::ranges::range<T2>); 45 static_assert(std::ranges::view<T2>); 46 static_assert(std::constructible_from<T2, T2>); 47 static_assert(std::ranges::borrowed_range<T2>); 48 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 54 // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=false) 55 struct T3 : test_range<cpp20_input_iterator>, std::ranges::view_base { 56 T3(T3 const&) = default; 57 }; 58 template<> constexpr bool std::ranges::enable_borrowed_range<T3> = false; 59 static_assert(std::ranges::range<T3>); 60 static_assert(std::ranges::view<T3>); 61 static_assert(std::constructible_from<T3, T3>); 62 static_assert(!std::ranges::borrowed_range<T3>); 63 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 69 // viewable_range<T> is not satisfied for (range=true, view=true, constructible_from=false, borrowed_range=true) 70 struct T4 : test_range<cpp20_input_iterator>, std::ranges::view_base { 71 T4(T4 const&) = delete; 72 T4(T4&&) = default; // necessary to model view 73 T4& operator=(T4&&) = default; // necessary to model view 74 }; 75 static_assert(std::ranges::range<T4 const&>); 76 static_assert(std::ranges::view<std::remove_cvref_t<T4 const&>>); 77 static_assert(!std::constructible_from<std::remove_cvref_t<T4 const&>, T4 const&>); 78 static_assert(std::ranges::borrowed_range<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, borrowed_range=false) can't be formed 83 84 // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=true, borrowed_range=true) 85 struct T5 : test_range<cpp20_input_iterator> { }; 86 template<> constexpr bool std::ranges::enable_borrowed_range<T5> = true; 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::ranges::borrowed_range<T5>); 91 92 static_assert(std::ranges::viewable_range<T5>); 93 94 // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, borrowed_range=false) 95 struct T6 : test_range<cpp20_input_iterator> { }; 96 template<> constexpr bool std::ranges::enable_borrowed_range<T6> = false; 97 static_assert(std::ranges::range<T6>); 98 static_assert(!std::ranges::view<T6>); 99 static_assert(std::constructible_from<T6, T6>); 100 static_assert(!std::ranges::borrowed_range<T6>); 101 102 static_assert(!std::ranges::viewable_range<T6>); 103 104 // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=false, borrowed_range=true) 105 struct T7 : test_range<cpp20_input_iterator> { 106 T7(T7 const&) = delete; 107 }; 108 static_assert(std::ranges::range<T7&>); 109 static_assert(!std::ranges::view<std::remove_cvref_t<T7&>>); 110 static_assert(!std::constructible_from<std::remove_cvref_t<T7&>, T7&>); 111 static_assert(std::ranges::borrowed_range<T7&>); 112 113 static_assert(std::ranges::viewable_range<T7&>); 114 115 // A type that satisfies (range=true, view=false, constructible_from=false, borrowed_range=false) can't be formed 116 struct T8 : test_range<cpp20_input_iterator> { 117 T8(T8 const&) = delete; 118 }; 119 static_assert(std::ranges::range<T8>); 120 static_assert(!std::ranges::view<T8>); 121 static_assert(!std::constructible_from<T8, T8>); 122 static_assert(!std::ranges::borrowed_range<T8>); 123 124 static_assert(!std::ranges::viewable_range<T8>); 125 126 // Test with a few degenerate types 127 static_assert(!std::ranges::viewable_range<void>); 128 static_assert(!std::ranges::viewable_range<int>); 129 static_assert(!std::ranges::viewable_range<int (*)(char)>); 130 static_assert(!std::ranges::viewable_range<int[]>); 131 static_assert(!std::ranges::viewable_range<int[10]>); 132 static_assert(!std::ranges::viewable_range<int(&)[]>); // unbounded array is not a range 133 static_assert( std::ranges::viewable_range<int(&)[10]>); 134