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 1171909de3SMark de Wever // UNSUPPORTED: libcpp-has-no-incomplete-ranges 123001b48dSLouis Dionne 133001b48dSLouis Dionne // template<class R> 143001b48dSLouis Dionne // concept viewable_range; 153001b48dSLouis Dionne 163001b48dSLouis Dionne #include <ranges> 173001b48dSLouis Dionne #include <type_traits> 183001b48dSLouis Dionne 193001b48dSLouis Dionne #include "test_iterators.h" 203001b48dSLouis Dionne #include "test_range.h" 213001b48dSLouis Dionne 223001b48dSLouis Dionne // The constraints we have in viewable_range are: 233001b48dSLouis Dionne // range<T> 243001b48dSLouis Dionne // view<remove_cvref_t<T>> 253001b48dSLouis Dionne // constructible_from<remove_cvref_t<T>, T> 26*67151d02SArthur O'Dwyer // lvalue_reference_t<T> || movable<remove_reference_t<T>> 27*67151d02SArthur O'Dwyer // is-initializer-list<T> 283001b48dSLouis Dionne // 293001b48dSLouis Dionne // We test all the relevant combinations of satisfying/not satisfying those constraints. 303001b48dSLouis Dionne 31*67151d02SArthur O'Dwyer // viewable_range<T> is not satisfied for (range=false, view=*, constructible_from=*, lvalue-or-movable=*) 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&>); 37*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T1&&>); 383001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1 const>); 393001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1 const&>); 40*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T1 const&&>); 413001b48dSLouis Dionne 42*67151d02SArthur O'Dwyer // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, lvalue-or-movable=true) 433001b48dSLouis Dionne struct T2 : test_range<cpp20_input_iterator>, std::ranges::view_base { 443001b48dSLouis Dionne T2(T2 const&) = default; 453001b48dSLouis Dionne }; 463001b48dSLouis Dionne static_assert(std::ranges::range<T2>); 473001b48dSLouis Dionne static_assert(std::ranges::view<T2>); 483001b48dSLouis Dionne static_assert(std::constructible_from<T2, T2>); 493001b48dSLouis Dionne 503001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2>); 513001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2&>); 52*67151d02SArthur O'Dwyer static_assert(std::ranges::viewable_range<T2&&>); 533001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2 const>); 543001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2 const&>); 55*67151d02SArthur O'Dwyer static_assert(std::ranges::viewable_range<T2 const&&>); 563001b48dSLouis Dionne 57*67151d02SArthur O'Dwyer // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, lvalue-or-movable=false) 583001b48dSLouis Dionne struct T3 : test_range<cpp20_input_iterator>, std::ranges::view_base { 593001b48dSLouis Dionne T3(T3 const&) = default; 603001b48dSLouis Dionne }; 613001b48dSLouis Dionne static_assert(std::ranges::range<T3>); 623001b48dSLouis Dionne static_assert(std::ranges::view<T3>); 633001b48dSLouis Dionne static_assert(std::constructible_from<T3, T3>); 643001b48dSLouis Dionne 653001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3>); 663001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3&>); 67*67151d02SArthur O'Dwyer static_assert(std::ranges::viewable_range<T3&&>); 683001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3 const>); 693001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3 const&>); 70*67151d02SArthur O'Dwyer static_assert(std::ranges::viewable_range<T3 const&&>); 713001b48dSLouis Dionne 72*67151d02SArthur O'Dwyer // viewable_range<T> is not satisfied for (range=true, view=true, constructible_from=false, lvalue-or-movable=true) 733001b48dSLouis Dionne struct T4 : test_range<cpp20_input_iterator>, std::ranges::view_base { 743001b48dSLouis Dionne T4(T4 const&) = delete; 753001b48dSLouis Dionne T4(T4&&) = default; // necessary to model view 763001b48dSLouis Dionne T4& operator=(T4&&) = default; // necessary to model view 773001b48dSLouis Dionne }; 783001b48dSLouis Dionne static_assert(std::ranges::range<T4 const&>); 793001b48dSLouis Dionne static_assert(std::ranges::view<std::remove_cvref_t<T4 const&>>); 803001b48dSLouis Dionne static_assert(!std::constructible_from<std::remove_cvref_t<T4 const&>, T4 const&>); 813001b48dSLouis Dionne 823001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T4 const&>); 833001b48dSLouis Dionne 84*67151d02SArthur O'Dwyer // A type that satisfies (range=true, view=true, constructible_from=false, lvalue-or-movable=false) can't be formed, 85*67151d02SArthur O'Dwyer // because views are movable by definition 863001b48dSLouis Dionne 87*67151d02SArthur O'Dwyer // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=true, lvalue-or-movable=true)... 883001b48dSLouis Dionne struct T5 : test_range<cpp20_input_iterator> { }; 893001b48dSLouis Dionne static_assert( std::ranges::range<T5>); 903001b48dSLouis Dionne static_assert(!std::ranges::view<T5>); 913001b48dSLouis Dionne static_assert( std::constructible_from<T5, T5>); 92*67151d02SArthur O'Dwyer static_assert( std::movable<T5>); 93*67151d02SArthur O'Dwyer static_assert(!std::movable<const T5>); 943001b48dSLouis Dionne 95*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T5>); // movable 96*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T5&>); // movable 97*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T5&&>); // movable 98*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T5>); 99*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T5&>); // lvalue 100*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T5&&>); 1013001b48dSLouis Dionne 102*67151d02SArthur O'Dwyer // ...but not if the (non-view, lvalue-or-movable) range is an initializer_list. 103*67151d02SArthur O'Dwyer static_assert( std::ranges::range<std::initializer_list<int>>); 104*67151d02SArthur O'Dwyer static_assert(!std::ranges::view<std::initializer_list<int>>); 105*67151d02SArthur O'Dwyer static_assert( std::constructible_from<std::initializer_list<int>, std::initializer_list<int>>); 106*67151d02SArthur O'Dwyer static_assert( std::movable<std::initializer_list<int>>); 107*67151d02SArthur O'Dwyer 108*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<std::initializer_list<int>>); 109*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<std::initializer_list<int>&>); 110*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<std::initializer_list<int>&&>); 111*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<std::initializer_list<int> const>); 112*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<std::initializer_list<int> const&>); 113*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<std::initializer_list<int> const&&>); 114*67151d02SArthur O'Dwyer 115*67151d02SArthur O'Dwyer // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, lvalue-or-movable=false) 116*67151d02SArthur O'Dwyer struct T6 : test_range<cpp20_input_iterator> { T6(T6&&); T6& operator=(T6&&) = delete; }; 1173001b48dSLouis Dionne static_assert( std::ranges::range<T6>); 1183001b48dSLouis Dionne static_assert(!std::ranges::view<T6>); 1193001b48dSLouis Dionne static_assert( std::constructible_from<T6, T6>); 120*67151d02SArthur O'Dwyer static_assert(!std::movable<T6>); 1213001b48dSLouis Dionne 1223001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T6>); 123*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T6&>); // lvalue 124*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T6&&>); 125*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T6>); 126*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T6&>); // lvalue 127*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T6&&>); 1283001b48dSLouis Dionne 129*67151d02SArthur O'Dwyer // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=false, lvalue-or-movable=true) 1303001b48dSLouis Dionne struct T7 : test_range<cpp20_input_iterator> { 1313001b48dSLouis Dionne T7(T7 const&) = delete; 1323001b48dSLouis Dionne }; 1333001b48dSLouis Dionne static_assert(std::ranges::range<T7&>); 1343001b48dSLouis Dionne static_assert(!std::ranges::view<std::remove_cvref_t<T7&>>); 1353001b48dSLouis Dionne static_assert(!std::constructible_from<std::remove_cvref_t<T7&>, T7&>); 1363001b48dSLouis Dionne 137*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T7>); 1383001b48dSLouis Dionne static_assert( std::ranges::viewable_range<T7&>); 139*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T7&&>); 140*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T7>); 141*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T7&>); 142*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T7&&>); 1433001b48dSLouis Dionne 144*67151d02SArthur O'Dwyer // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=false, lvalue-or-movable=false) 1453001b48dSLouis Dionne struct T8 : test_range<cpp20_input_iterator> { 1463001b48dSLouis Dionne T8(T8 const&) = delete; 1473001b48dSLouis Dionne }; 1483001b48dSLouis Dionne static_assert(std::ranges::range<T8>); 1493001b48dSLouis Dionne static_assert(!std::ranges::view<T8>); 1503001b48dSLouis Dionne static_assert(!std::constructible_from<T8, T8>); 1513001b48dSLouis Dionne 1523001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T8>); 153*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T8&>); 154*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T8&&>); 155*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T8>); 156*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T8&>); 157*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T8&&>); 1583001b48dSLouis Dionne 1593001b48dSLouis Dionne // Test with a few degenerate types 1603001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<void>); 1613001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int>); 1623001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int (*)(char)>); 1633001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int[]>); 1643001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int[10]>); 165*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<int(&)[]>); // not a range 166*67151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<int(&)[10]>); // OK, lvalue 167*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<int(&&)[]>); 168*67151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<int(&&)[10]>); 169