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