1*3001b48dSLouis Dionne //===----------------------------------------------------------------------===// 2*3001b48dSLouis Dionne // 3*3001b48dSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*3001b48dSLouis Dionne // See https://llvm.org/LICENSE.txt for license information. 5*3001b48dSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*3001b48dSLouis Dionne // 7*3001b48dSLouis Dionne //===----------------------------------------------------------------------===// 8*3001b48dSLouis Dionne 9*3001b48dSLouis Dionne // UNSUPPORTED: c++03, c++11, c++14, c++17 10*3001b48dSLouis Dionne // UNSUPPORTED: libcpp-no-concepts 11*3001b48dSLouis Dionne // UNSUPPORTED: gcc-10 12*3001b48dSLouis Dionne 13*3001b48dSLouis Dionne // template<class R> 14*3001b48dSLouis Dionne // concept viewable_range; 15*3001b48dSLouis Dionne 16*3001b48dSLouis Dionne #include <ranges> 17*3001b48dSLouis Dionne #include <type_traits> 18*3001b48dSLouis Dionne 19*3001b48dSLouis Dionne #include "test_iterators.h" 20*3001b48dSLouis Dionne #include "test_range.h" 21*3001b48dSLouis Dionne 22*3001b48dSLouis Dionne // The constraints we have in viewable_range are: 23*3001b48dSLouis Dionne // range<T> 24*3001b48dSLouis Dionne // view<remove_cvref_t<T>> 25*3001b48dSLouis Dionne // constructible_from<remove_cvref_t<T>, T> 26*3001b48dSLouis Dionne // borrowed_range<T> 27*3001b48dSLouis Dionne // 28*3001b48dSLouis Dionne // We test all the relevant combinations of satisfying/not satisfying those constraints. 29*3001b48dSLouis Dionne 30*3001b48dSLouis Dionne // viewable_range<T> is not satisfied for (range=false, view=*, constructible_from=*, borrowed_range=*) 31*3001b48dSLouis Dionne struct T1 { }; 32*3001b48dSLouis Dionne static_assert(!std::ranges::range<T1>); 33*3001b48dSLouis Dionne 34*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1>); 35*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1&>); 36*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1 const>); 37*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1 const&>); 38*3001b48dSLouis Dionne 39*3001b48dSLouis Dionne // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=true) 40*3001b48dSLouis Dionne struct T2 : test_range<cpp20_input_iterator>, std::ranges::view_base { 41*3001b48dSLouis Dionne T2(T2 const&) = default; 42*3001b48dSLouis Dionne }; 43*3001b48dSLouis Dionne template<> constexpr bool std::ranges::enable_borrowed_range<T2> = true; 44*3001b48dSLouis Dionne static_assert(std::ranges::range<T2>); 45*3001b48dSLouis Dionne static_assert(std::ranges::view<T2>); 46*3001b48dSLouis Dionne static_assert(std::constructible_from<T2, T2>); 47*3001b48dSLouis Dionne static_assert(std::ranges::borrowed_range<T2>); 48*3001b48dSLouis Dionne 49*3001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2>); 50*3001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2&>); 51*3001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2 const>); 52*3001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2 const&>); 53*3001b48dSLouis Dionne 54*3001b48dSLouis Dionne // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=false) 55*3001b48dSLouis Dionne struct T3 : test_range<cpp20_input_iterator>, std::ranges::view_base { 56*3001b48dSLouis Dionne T3(T3 const&) = default; 57*3001b48dSLouis Dionne }; 58*3001b48dSLouis Dionne template<> constexpr bool std::ranges::enable_borrowed_range<T3> = false; 59*3001b48dSLouis Dionne static_assert(std::ranges::range<T3>); 60*3001b48dSLouis Dionne static_assert(std::ranges::view<T3>); 61*3001b48dSLouis Dionne static_assert(std::constructible_from<T3, T3>); 62*3001b48dSLouis Dionne static_assert(!std::ranges::borrowed_range<T3>); 63*3001b48dSLouis Dionne 64*3001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3>); 65*3001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3&>); 66*3001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3 const>); 67*3001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3 const&>); 68*3001b48dSLouis Dionne 69*3001b48dSLouis Dionne // viewable_range<T> is not satisfied for (range=true, view=true, constructible_from=false, borrowed_range=true) 70*3001b48dSLouis Dionne struct T4 : test_range<cpp20_input_iterator>, std::ranges::view_base { 71*3001b48dSLouis Dionne T4(T4 const&) = delete; 72*3001b48dSLouis Dionne T4(T4&&) = default; // necessary to model view 73*3001b48dSLouis Dionne T4& operator=(T4&&) = default; // necessary to model view 74*3001b48dSLouis Dionne }; 75*3001b48dSLouis Dionne static_assert(std::ranges::range<T4 const&>); 76*3001b48dSLouis Dionne static_assert(std::ranges::view<std::remove_cvref_t<T4 const&>>); 77*3001b48dSLouis Dionne static_assert(!std::constructible_from<std::remove_cvref_t<T4 const&>, T4 const&>); 78*3001b48dSLouis Dionne static_assert(std::ranges::borrowed_range<T4 const&>); 79*3001b48dSLouis Dionne 80*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T4 const&>); 81*3001b48dSLouis Dionne 82*3001b48dSLouis Dionne // A type that satisfies (range=true, view=true, constructible_from=false, borrowed_range=false) can't be formed 83*3001b48dSLouis Dionne 84*3001b48dSLouis Dionne // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=true, borrowed_range=true) 85*3001b48dSLouis Dionne struct T5 : test_range<cpp20_input_iterator> { }; 86*3001b48dSLouis Dionne template<> constexpr bool std::ranges::enable_borrowed_range<T5> = true; 87*3001b48dSLouis Dionne static_assert(std::ranges::range<T5>); 88*3001b48dSLouis Dionne static_assert(!std::ranges::view<T5>); 89*3001b48dSLouis Dionne static_assert(std::constructible_from<T5, T5>); 90*3001b48dSLouis Dionne static_assert(std::ranges::borrowed_range<T5>); 91*3001b48dSLouis Dionne 92*3001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T5>); 93*3001b48dSLouis Dionne 94*3001b48dSLouis Dionne // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, borrowed_range=false) 95*3001b48dSLouis Dionne struct T6 : test_range<cpp20_input_iterator> { }; 96*3001b48dSLouis Dionne template<> constexpr bool std::ranges::enable_borrowed_range<T6> = false; 97*3001b48dSLouis Dionne static_assert(std::ranges::range<T6>); 98*3001b48dSLouis Dionne static_assert(!std::ranges::view<T6>); 99*3001b48dSLouis Dionne static_assert(std::constructible_from<T6, T6>); 100*3001b48dSLouis Dionne static_assert(!std::ranges::borrowed_range<T6>); 101*3001b48dSLouis Dionne 102*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T6>); 103*3001b48dSLouis Dionne 104*3001b48dSLouis Dionne // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=false, borrowed_range=true) 105*3001b48dSLouis Dionne struct T7 : test_range<cpp20_input_iterator> { 106*3001b48dSLouis Dionne T7(T7 const&) = delete; 107*3001b48dSLouis Dionne }; 108*3001b48dSLouis Dionne static_assert(std::ranges::range<T7&>); 109*3001b48dSLouis Dionne static_assert(!std::ranges::view<std::remove_cvref_t<T7&>>); 110*3001b48dSLouis Dionne static_assert(!std::constructible_from<std::remove_cvref_t<T7&>, T7&>); 111*3001b48dSLouis Dionne static_assert(std::ranges::borrowed_range<T7&>); 112*3001b48dSLouis Dionne 113*3001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T7&>); 114*3001b48dSLouis Dionne 115*3001b48dSLouis Dionne // A type that satisfies (range=true, view=false, constructible_from=false, borrowed_range=false) can't be formed 116*3001b48dSLouis Dionne struct T8 : test_range<cpp20_input_iterator> { 117*3001b48dSLouis Dionne T8(T8 const&) = delete; 118*3001b48dSLouis Dionne }; 119*3001b48dSLouis Dionne static_assert(std::ranges::range<T8>); 120*3001b48dSLouis Dionne static_assert(!std::ranges::view<T8>); 121*3001b48dSLouis Dionne static_assert(!std::constructible_from<T8, T8>); 122*3001b48dSLouis Dionne static_assert(!std::ranges::borrowed_range<T8>); 123*3001b48dSLouis Dionne 124*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T8>); 125*3001b48dSLouis Dionne 126*3001b48dSLouis Dionne // Test with a few degenerate types 127*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<void>); 128*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int>); 129*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int (*)(char)>); 130*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int[]>); 131*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int[10]>); 132*3001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int(&)[]>); // unbounded array is not a range 133*3001b48dSLouis Dionne static_assert( std::ranges::viewable_range<int(&)[10]>); 134