xref: /llvm-project/libcxx/test/std/ranges/range.req/range.refinements/viewable_range.compile.pass.cpp (revision b8cb1dc9ea87faa8e8e9ab7a31710a8c0bb8b084)
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