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