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> 2667151d02SArthur O'Dwyer // lvalue_reference_t<T> || movable<remove_reference_t<T>> 2767151d02SArthur O'Dwyer // is-initializer-list<T> 283001b48dSLouis Dionne // 293001b48dSLouis Dionne // We test all the relevant combinations of satisfying/not satisfying those constraints. 303001b48dSLouis Dionne 3167151d02SArthur 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&>); 3767151d02SArthur 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&>); 4067151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T1 const&&>); 413001b48dSLouis Dionne 4267151d02SArthur 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&>); 5267151d02SArthur 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&>); 5567151d02SArthur O'Dwyer static_assert(std::ranges::viewable_range<T2 const&&>); 563001b48dSLouis Dionne 5767151d02SArthur 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&>); 6767151d02SArthur 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&>); 7067151d02SArthur O'Dwyer static_assert(std::ranges::viewable_range<T3 const&&>); 713001b48dSLouis Dionne 7267151d02SArthur 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 8467151d02SArthur O'Dwyer // A type that satisfies (range=true, view=true, constructible_from=false, lvalue-or-movable=false) can't be formed, 8567151d02SArthur O'Dwyer // because views are movable by definition 863001b48dSLouis Dionne 8767151d02SArthur 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>); 9267151d02SArthur O'Dwyer static_assert( std::movable<T5>); 9367151d02SArthur O'Dwyer static_assert(!std::movable<const T5>); 943001b48dSLouis Dionne 9567151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T5>); // movable 9667151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T5&>); // movable 9767151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T5&&>); // movable 9867151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T5>); 9967151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T5&>); // lvalue 10067151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T5&&>); 1013001b48dSLouis Dionne 10267151d02SArthur O'Dwyer // ...but not if the (non-view, lvalue-or-movable) range is an initializer_list. 10367151d02SArthur O'Dwyer static_assert( std::ranges::range<std::initializer_list<int>>); 10467151d02SArthur O'Dwyer static_assert(!std::ranges::view<std::initializer_list<int>>); 10567151d02SArthur O'Dwyer static_assert( std::constructible_from<std::initializer_list<int>, std::initializer_list<int>>); 10667151d02SArthur O'Dwyer static_assert( std::movable<std::initializer_list<int>>); 10767151d02SArthur O'Dwyer 10867151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<std::initializer_list<int>>); 10967151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<std::initializer_list<int>&>); 11067151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<std::initializer_list<int>&&>); 11167151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<std::initializer_list<int> const>); 11267151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<std::initializer_list<int> const&>); 11367151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<std::initializer_list<int> const&&>); 11467151d02SArthur O'Dwyer 11567151d02SArthur O'Dwyer // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, lvalue-or-movable=false) 11667151d02SArthur 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>); 12067151d02SArthur O'Dwyer static_assert(!std::movable<T6>); 1213001b48dSLouis Dionne 1223001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T6>); 12367151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T6&>); // lvalue 12467151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T6&&>); 12567151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T6>); 12667151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T6&>); // lvalue 12767151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T6&&>); 1283001b48dSLouis Dionne 12967151d02SArthur 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 13767151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T7>); 1383001b48dSLouis Dionne static_assert( std::ranges::viewable_range<T7&>); 13967151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T7&&>); 14067151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T7>); 14167151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T7&>); 14267151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T7&&>); 1433001b48dSLouis Dionne 14467151d02SArthur 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>); 15367151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T8&>); 15467151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T8&&>); 15567151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T8>); 15667151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T8&>); 15767151d02SArthur 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]>); 16567151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<int(&)[]>); // not a range 16667151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<int(&)[10]>); // OK, lvalue 16767151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<int(&&)[]>); 16867151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<int(&&)[10]>); 169*bf150e8dSArthur O'Dwyer 170*bf150e8dSArthur O'Dwyer // Test ADL-proofing. 171*bf150e8dSArthur O'Dwyer struct Incomplete; 172*bf150e8dSArthur O'Dwyer template<class T> struct Holder { T t; }; 173*bf150e8dSArthur O'Dwyer 174*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>*>); 175*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>*&>); 176*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>*&&>); 177*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const>); 178*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const&>); 179*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const&&>); 180*bf150e8dSArthur O'Dwyer 181*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>*[10]>); 182*bf150e8dSArthur O'Dwyer static_assert( std::ranges::viewable_range<Holder<Incomplete>*(&)[10]>); 183*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>*(&&)[10]>); 184*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const[10]>); 185*bf150e8dSArthur O'Dwyer static_assert( std::ranges::viewable_range<Holder<Incomplete>* const(&)[10]>); 186*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const(&&)[10]>); 187