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 113001b48dSLouis Dionne // template<class R> 123001b48dSLouis Dionne // concept viewable_range; 133001b48dSLouis Dionne 143001b48dSLouis Dionne #include <ranges> 153001b48dSLouis Dionne #include <type_traits> 163001b48dSLouis Dionne 173001b48dSLouis Dionne #include "test_iterators.h" 183001b48dSLouis Dionne #include "test_range.h" 193001b48dSLouis Dionne 203001b48dSLouis Dionne // The constraints we have in viewable_range are: 213001b48dSLouis Dionne // range<T> 223001b48dSLouis Dionne // view<remove_cvref_t<T>> 233001b48dSLouis Dionne // constructible_from<remove_cvref_t<T>, T> 2467151d02SArthur O'Dwyer // lvalue_reference_t<T> || movable<remove_reference_t<T>> 2567151d02SArthur O'Dwyer // is-initializer-list<T> 263001b48dSLouis Dionne // 273001b48dSLouis Dionne // We test all the relevant combinations of satisfying/not satisfying those constraints. 283001b48dSLouis Dionne 2967151d02SArthur O'Dwyer // viewable_range<T> is not satisfied for (range=false, view=*, constructible_from=*, lvalue-or-movable=*) 303001b48dSLouis Dionne struct T1 { }; 313001b48dSLouis Dionne static_assert(!std::ranges::range<T1>); 323001b48dSLouis Dionne 333001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1>); 343001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1&>); 3567151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T1&&>); 363001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1 const>); 373001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T1 const&>); 3867151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T1 const&&>); 393001b48dSLouis Dionne 4067151d02SArthur O'Dwyer // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, lvalue-or-movable=true) 413001b48dSLouis Dionne struct T2 : test_range<cpp20_input_iterator>, std::ranges::view_base { 423001b48dSLouis Dionne T2(T2 const&) = default; 433001b48dSLouis Dionne }; 443001b48dSLouis Dionne static_assert(std::ranges::range<T2>); 453001b48dSLouis Dionne static_assert(std::ranges::view<T2>); 463001b48dSLouis Dionne static_assert(std::constructible_from<T2, T2>); 473001b48dSLouis Dionne 483001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2>); 493001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2&>); 5067151d02SArthur O'Dwyer static_assert(std::ranges::viewable_range<T2&&>); 513001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2 const>); 523001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T2 const&>); 5367151d02SArthur O'Dwyer static_assert(std::ranges::viewable_range<T2 const&&>); 543001b48dSLouis Dionne 5567151d02SArthur O'Dwyer // viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, lvalue-or-movable=false) 563001b48dSLouis Dionne struct T3 : test_range<cpp20_input_iterator>, std::ranges::view_base { 573001b48dSLouis Dionne T3(T3 const&) = default; 583001b48dSLouis Dionne }; 593001b48dSLouis Dionne static_assert(std::ranges::range<T3>); 603001b48dSLouis Dionne static_assert(std::ranges::view<T3>); 613001b48dSLouis Dionne static_assert(std::constructible_from<T3, T3>); 623001b48dSLouis Dionne 633001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3>); 643001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3&>); 6567151d02SArthur O'Dwyer static_assert(std::ranges::viewable_range<T3&&>); 663001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3 const>); 673001b48dSLouis Dionne static_assert(std::ranges::viewable_range<T3 const&>); 6867151d02SArthur O'Dwyer static_assert(std::ranges::viewable_range<T3 const&&>); 693001b48dSLouis Dionne 7067151d02SArthur O'Dwyer // viewable_range<T> is not satisfied for (range=true, view=true, constructible_from=false, lvalue-or-movable=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 803001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T4 const&>); 813001b48dSLouis Dionne 8267151d02SArthur O'Dwyer // A type that satisfies (range=true, view=true, constructible_from=false, lvalue-or-movable=false) can't be formed, 8367151d02SArthur O'Dwyer // because views are movable by definition 843001b48dSLouis Dionne 8567151d02SArthur O'Dwyer // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=true, lvalue-or-movable=true)... 863001b48dSLouis Dionne struct T5 : test_range<cpp20_input_iterator> { }; 873001b48dSLouis Dionne static_assert( std::ranges::range<T5>); 883001b48dSLouis Dionne static_assert(!std::ranges::view<T5>); 893001b48dSLouis Dionne static_assert( std::constructible_from<T5, T5>); 9067151d02SArthur O'Dwyer static_assert( std::movable<T5>); 9167151d02SArthur O'Dwyer static_assert(!std::movable<const T5>); 923001b48dSLouis Dionne 9367151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T5>); // movable 9467151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T5&>); // movable 9567151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T5&&>); // movable 9667151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T5>); 9767151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T5&>); // lvalue 9867151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T5&&>); 993001b48dSLouis Dionne 10067151d02SArthur O'Dwyer // ...but not if the (non-view, lvalue-or-movable) range is an initializer_list. 10167151d02SArthur O'Dwyer static_assert( std::ranges::range<std::initializer_list<int>>); 10267151d02SArthur O'Dwyer static_assert(!std::ranges::view<std::initializer_list<int>>); 10367151d02SArthur O'Dwyer static_assert( std::constructible_from<std::initializer_list<int>, std::initializer_list<int>>); 10467151d02SArthur O'Dwyer static_assert( std::movable<std::initializer_list<int>>); 10567151d02SArthur O'Dwyer 10667151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<std::initializer_list<int>>); 10767151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<std::initializer_list<int>&>); 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> const>); 11067151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<std::initializer_list<int> const&>); 11167151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<std::initializer_list<int> const&&>); 11267151d02SArthur O'Dwyer 11367151d02SArthur O'Dwyer // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, lvalue-or-movable=false) 11467151d02SArthur O'Dwyer struct T6 : test_range<cpp20_input_iterator> { T6(T6&&); T6& operator=(T6&&) = delete; }; 1153001b48dSLouis Dionne static_assert( std::ranges::range<T6>); 1163001b48dSLouis Dionne static_assert(!std::ranges::view<T6>); 1173001b48dSLouis Dionne static_assert( std::constructible_from<T6, T6>); 11867151d02SArthur O'Dwyer static_assert(!std::movable<T6>); 1193001b48dSLouis Dionne 1203001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T6>); 12167151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T6&>); // lvalue 12267151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T6&&>); 12367151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T6>); 12467151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T6&>); // lvalue 12567151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T6&&>); 1263001b48dSLouis Dionne 12767151d02SArthur O'Dwyer // viewable_range<T> is satisfied for (range=true, view=false, constructible_from=false, lvalue-or-movable=true) 1283001b48dSLouis Dionne struct T7 : test_range<cpp20_input_iterator> { 1293001b48dSLouis Dionne T7(T7 const&) = delete; 1303001b48dSLouis Dionne }; 1313001b48dSLouis Dionne static_assert(std::ranges::range<T7&>); 1323001b48dSLouis Dionne static_assert(!std::ranges::view<std::remove_cvref_t<T7&>>); 1333001b48dSLouis Dionne static_assert(!std::constructible_from<std::remove_cvref_t<T7&>, T7&>); 1343001b48dSLouis Dionne 13567151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T7>); 1363001b48dSLouis Dionne static_assert( std::ranges::viewable_range<T7&>); 13767151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T7&&>); 13867151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T7>); 13967151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T7&>); 14067151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T7&&>); 1413001b48dSLouis Dionne 14267151d02SArthur O'Dwyer // viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=false, lvalue-or-movable=false) 1433001b48dSLouis Dionne struct T8 : test_range<cpp20_input_iterator> { 1443001b48dSLouis Dionne T8(T8 const&) = delete; 1453001b48dSLouis Dionne }; 1463001b48dSLouis Dionne static_assert(std::ranges::range<T8>); 1473001b48dSLouis Dionne static_assert(!std::ranges::view<T8>); 1483001b48dSLouis Dionne static_assert(!std::constructible_from<T8, T8>); 1493001b48dSLouis Dionne 1503001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<T8>); 15167151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<T8&>); 15267151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<T8&&>); 15367151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T8>); 15467151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<const T8&>); 15567151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<const T8&&>); 1563001b48dSLouis Dionne 1573001b48dSLouis Dionne // Test with a few degenerate types 1583001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<void>); 1593001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int>); 1603001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int (*)(char)>); 1613001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int[]>); 1623001b48dSLouis Dionne static_assert(!std::ranges::viewable_range<int[10]>); 16367151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<int(&)[]>); // not a range 16467151d02SArthur O'Dwyer static_assert( std::ranges::viewable_range<int(&)[10]>); // OK, lvalue 16567151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<int(&&)[]>); 16667151d02SArthur O'Dwyer static_assert(!std::ranges::viewable_range<int(&&)[10]>); 167*bf150e8dSArthur O'Dwyer 168*bf150e8dSArthur O'Dwyer // Test ADL-proofing. 169*bf150e8dSArthur O'Dwyer struct Incomplete; 170*bf150e8dSArthur O'Dwyer template<class T> struct Holder { T t; }; 171*bf150e8dSArthur O'Dwyer 172*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>*>); 173*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>*&>); 174*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>*&&>); 175*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const>); 176*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const&>); 177*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const&&>); 178*bf150e8dSArthur O'Dwyer 179*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>*[10]>); 180*bf150e8dSArthur O'Dwyer static_assert( std::ranges::viewable_range<Holder<Incomplete>*(&)[10]>); 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>* const[10]>); 183*bf150e8dSArthur O'Dwyer static_assert( std::ranges::viewable_range<Holder<Incomplete>* const(&)[10]>); 184*bf150e8dSArthur O'Dwyer static_assert(!std::ranges::viewable_range<Holder<Incomplete>* const(&&)[10]>); 185