13001b48dSLouis Dionne //===----------------------------------------------------------------------===//
23001b48dSLouis Dionne //
33001b48dSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43001b48dSLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
53001b48dSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63001b48dSLouis Dionne //
73001b48dSLouis Dionne //===----------------------------------------------------------------------===//
83001b48dSLouis Dionne 
93001b48dSLouis Dionne // UNSUPPORTED: c++03, c++11, c++14, c++17
103001b48dSLouis Dionne // UNSUPPORTED: libcpp-no-concepts
113001b48dSLouis Dionne // UNSUPPORTED: gcc-10
12*71909de3SMark de Wever // UNSUPPORTED: libcpp-has-no-incomplete-ranges
133001b48dSLouis Dionne 
143001b48dSLouis Dionne // template<class R>
153001b48dSLouis Dionne // concept viewable_range;
163001b48dSLouis Dionne 
173001b48dSLouis Dionne #include <ranges>
183001b48dSLouis Dionne #include <type_traits>
193001b48dSLouis Dionne 
203001b48dSLouis Dionne #include "test_iterators.h"
213001b48dSLouis Dionne #include "test_range.h"
223001b48dSLouis Dionne 
233001b48dSLouis Dionne // The constraints we have in viewable_range are:
243001b48dSLouis Dionne //  range<T>
253001b48dSLouis Dionne //  view<remove_cvref_t<T>>
263001b48dSLouis Dionne //  constructible_from<remove_cvref_t<T>, T>
273001b48dSLouis Dionne //  borrowed_range<T>
283001b48dSLouis Dionne //
293001b48dSLouis Dionne // We test all the relevant combinations of satisfying/not satisfying those constraints.
303001b48dSLouis Dionne 
313001b48dSLouis Dionne // viewable_range<T> is not satisfied for (range=false, view=*, constructible_from=*, borrowed_range=*)
323001b48dSLouis Dionne struct T1 { };
333001b48dSLouis Dionne static_assert(!std::ranges::range<T1>);
343001b48dSLouis Dionne 
353001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1>);
363001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1&>);
373001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1 const>);
383001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1 const&>);
393001b48dSLouis Dionne 
403001b48dSLouis Dionne // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=true)
413001b48dSLouis Dionne struct T2 : test_range<cpp20_input_iterator>, std::ranges::view_base {
423001b48dSLouis Dionne   T2(T2 const&) = default;
433001b48dSLouis Dionne };
443001b48dSLouis Dionne template<> constexpr bool std::ranges::enable_borrowed_range<T2> = true;
453001b48dSLouis Dionne static_assert(std::ranges::range<T2>);
463001b48dSLouis Dionne static_assert(std::ranges::view<T2>);
473001b48dSLouis Dionne static_assert(std::constructible_from<T2, T2>);
483001b48dSLouis Dionne static_assert(std::ranges::borrowed_range<T2>);
493001b48dSLouis Dionne 
503001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2>);
513001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2&>);
523001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2 const>);
533001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2 const&>);
543001b48dSLouis Dionne 
553001b48dSLouis Dionne // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=false)
563001b48dSLouis Dionne struct T3 : test_range<cpp20_input_iterator>, std::ranges::view_base {
573001b48dSLouis Dionne   T3(T3 const&) = default;
583001b48dSLouis Dionne };
593001b48dSLouis Dionne template<> constexpr bool std::ranges::enable_borrowed_range<T3> = false;
603001b48dSLouis Dionne static_assert(std::ranges::range<T3>);
613001b48dSLouis Dionne static_assert(std::ranges::view<T3>);
623001b48dSLouis Dionne static_assert(std::constructible_from<T3, T3>);
633001b48dSLouis Dionne static_assert(!std::ranges::borrowed_range<T3>);
643001b48dSLouis Dionne 
653001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3>);
663001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3&>);
673001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3 const>);
683001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3 const&>);
693001b48dSLouis Dionne 
703001b48dSLouis Dionne // viewable_range<T> is not satisfied for (range=true, view=true, constructible_from=false, borrowed_range=true)
713001b48dSLouis Dionne struct T4 : test_range<cpp20_input_iterator>, std::ranges::view_base {
723001b48dSLouis Dionne   T4(T4 const&) = delete;
733001b48dSLouis Dionne   T4(T4&&) = default;             // necessary to model view
743001b48dSLouis Dionne   T4& operator=(T4&&) = default;  // necessary to model view
753001b48dSLouis Dionne };
763001b48dSLouis Dionne static_assert(std::ranges::range<T4 const&>);
773001b48dSLouis Dionne static_assert(std::ranges::view<std::remove_cvref_t<T4 const&>>);
783001b48dSLouis Dionne static_assert(!std::constructible_from<std::remove_cvref_t<T4 const&>, T4 const&>);
793001b48dSLouis Dionne static_assert(std::ranges::borrowed_range<T4 const&>);
803001b48dSLouis Dionne 
813001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T4 const&>);
823001b48dSLouis Dionne 
833001b48dSLouis Dionne // A type that satisfies (range=true, view=true, constructible_from=false, borrowed_range=false) can't be formed
843001b48dSLouis Dionne 
853001b48dSLouis Dionne // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=true, borrowed_range=true)
863001b48dSLouis Dionne struct T5 : test_range<cpp20_input_iterator> { };
873001b48dSLouis Dionne template<> constexpr bool std::ranges::enable_borrowed_range<T5> = true;
883001b48dSLouis Dionne static_assert(std::ranges::range<T5>);
893001b48dSLouis Dionne static_assert(!std::ranges::view<T5>);
903001b48dSLouis Dionne static_assert(std::constructible_from<T5, T5>);
913001b48dSLouis Dionne static_assert(std::ranges::borrowed_range<T5>);
923001b48dSLouis Dionne 
933001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T5>);
943001b48dSLouis Dionne 
953001b48dSLouis Dionne // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, borrowed_range=false)
963001b48dSLouis Dionne struct T6 : test_range<cpp20_input_iterator> { };
973001b48dSLouis Dionne template<> constexpr bool std::ranges::enable_borrowed_range<T6> = false;
983001b48dSLouis Dionne static_assert(std::ranges::range<T6>);
993001b48dSLouis Dionne static_assert(!std::ranges::view<T6>);
1003001b48dSLouis Dionne static_assert(std::constructible_from<T6, T6>);
1013001b48dSLouis Dionne static_assert(!std::ranges::borrowed_range<T6>);
1023001b48dSLouis Dionne 
1033001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T6>);
1043001b48dSLouis Dionne 
1053001b48dSLouis Dionne // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=false, borrowed_range=true)
1063001b48dSLouis Dionne struct T7 : test_range<cpp20_input_iterator> {
1073001b48dSLouis Dionne   T7(T7 const&) = delete;
1083001b48dSLouis Dionne };
1093001b48dSLouis Dionne static_assert(std::ranges::range<T7&>);
1103001b48dSLouis Dionne static_assert(!std::ranges::view<std::remove_cvref_t<T7&>>);
1113001b48dSLouis Dionne static_assert(!std::constructible_from<std::remove_cvref_t<T7&>, T7&>);
1123001b48dSLouis Dionne static_assert(std::ranges::borrowed_range<T7&>);
1133001b48dSLouis Dionne 
1143001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T7&>);
1153001b48dSLouis Dionne 
1163001b48dSLouis Dionne // A type that satisfies (range=true, view=false, constructible_from=false, borrowed_range=false) can't be formed
1173001b48dSLouis Dionne struct T8 : test_range<cpp20_input_iterator> {
1183001b48dSLouis Dionne   T8(T8 const&) = delete;
1193001b48dSLouis Dionne };
1203001b48dSLouis Dionne static_assert(std::ranges::range<T8>);
1213001b48dSLouis Dionne static_assert(!std::ranges::view<T8>);
1223001b48dSLouis Dionne static_assert(!std::constructible_from<T8, T8>);
1233001b48dSLouis Dionne static_assert(!std::ranges::borrowed_range<T8>);
1243001b48dSLouis Dionne 
1253001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T8>);
1263001b48dSLouis Dionne 
1273001b48dSLouis Dionne // Test with a few degenerate types
1283001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<void>);
1293001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int>);
1303001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int (*)(char)>);
1313001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int[]>);
1323001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int[10]>);
1333001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int(&)[]>); // unbounded array is not a range
1343001b48dSLouis Dionne static_assert( std::ranges::viewable_range<int(&)[10]>);
135