15671ff20Szoecarver //===----------------------------------------------------------------------===//
25671ff20Szoecarver //
35671ff20Szoecarver // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45671ff20Szoecarver // See https://llvm.org/LICENSE.txt for license information.
55671ff20Szoecarver // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65671ff20Szoecarver //
75671ff20Szoecarver //===----------------------------------------------------------------------===//
85671ff20Szoecarver
95671ff20Szoecarver // UNSUPPORTED: c++03, c++11, c++14, c++17
105671ff20Szoecarver
115671ff20Szoecarver // template<class D>
125671ff20Szoecarver // requires is_class_v<D> && same_as<D, remove_cv_t<D>>
135671ff20Szoecarver // class view_interface;
145671ff20Szoecarver
155671ff20Szoecarver #include <ranges>
165671ff20Szoecarver
175671ff20Szoecarver #include <cassert>
1817e6bd80SKonstantin Varlamov #include <utility>
195671ff20Szoecarver #include "test_macros.h"
205671ff20Szoecarver #include "test_iterators.h"
215671ff20Szoecarver
225671ff20Szoecarver template<class T>
235671ff20Szoecarver concept ValidViewInterfaceType = requires { typename std::ranges::view_interface<T>; };
245671ff20Szoecarver
255671ff20Szoecarver struct Empty { };
265671ff20Szoecarver
275671ff20Szoecarver static_assert(!ValidViewInterfaceType<void>);
285671ff20Szoecarver static_assert(!ValidViewInterfaceType<void*>);
295671ff20Szoecarver static_assert(!ValidViewInterfaceType<Empty*>);
305671ff20Szoecarver static_assert(!ValidViewInterfaceType<Empty const>);
315671ff20Szoecarver static_assert(!ValidViewInterfaceType<Empty &>);
325671ff20Szoecarver static_assert( ValidViewInterfaceType<Empty>);
335671ff20Szoecarver
345671ff20Szoecarver using InputIter = cpp20_input_iterator<const int*>;
355671ff20Szoecarver
365671ff20Szoecarver struct InputRange : std::ranges::view_interface<InputRange> {
375671ff20Szoecarver int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginInputRange385671ff20Szoecarver constexpr InputIter begin() const { return InputIter(buff); }
endInputRange395671ff20Szoecarver constexpr InputIter end() const { return InputIter(buff + 8); }
405671ff20Szoecarver };
415671ff20Szoecarver
42*cf09b7deSXiaoyang Liu struct SizedInputRange : std::ranges::view_interface<SizedInputRange> {
43*cf09b7deSXiaoyang Liu int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginSizedInputRange44*cf09b7deSXiaoyang Liu constexpr InputIter begin() const { return InputIter(buff); }
endSizedInputRange45*cf09b7deSXiaoyang Liu constexpr sentinel_wrapper<InputIter> end() const { return sentinel_wrapper(InputIter(buff + 8)); }
sizeSizedInputRange46*cf09b7deSXiaoyang Liu constexpr std::size_t size() const { return 8; }
47*cf09b7deSXiaoyang Liu };
48*cf09b7deSXiaoyang Liu static_assert(std::ranges::sized_range<SizedInputRange>);
49*cf09b7deSXiaoyang Liu
505671ff20Szoecarver struct NotSizedSentinel {
51389e749cSArthur O'Dwyer using value_type = int;
52389e749cSArthur O'Dwyer using difference_type = std::ptrdiff_t;
535671ff20Szoecarver using iterator_concept = std::forward_iterator_tag;
545671ff20Szoecarver
55389e749cSArthur O'Dwyer explicit NotSizedSentinel() = default;
56389e749cSArthur O'Dwyer explicit NotSizedSentinel(int*);
57389e749cSArthur O'Dwyer int& operator*() const;
585671ff20Szoecarver NotSizedSentinel& operator++();
595671ff20Szoecarver NotSizedSentinel operator++(int);
605671ff20Szoecarver bool operator==(NotSizedSentinel const&) const;
615671ff20Szoecarver };
625671ff20Szoecarver static_assert(std::forward_iterator<NotSizedSentinel>);
635671ff20Szoecarver
645671ff20Szoecarver using ForwardIter = forward_iterator<int*>;
655671ff20Szoecarver
665671ff20Szoecarver // So that we conform to sized_sentinel_for.
operator -(const ForwardIter & x,const ForwardIter & y)675671ff20Szoecarver constexpr std::ptrdiff_t operator-(const ForwardIter& x, const ForwardIter& y) {
685f26d863SMark de Wever return base(x) - base(y);
695671ff20Szoecarver }
705671ff20Szoecarver
715671ff20Szoecarver struct ForwardRange : std::ranges::view_interface<ForwardRange> {
725671ff20Szoecarver int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginForwardRange735671ff20Szoecarver constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
endForwardRange745671ff20Szoecarver constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }
755671ff20Szoecarver };
76c3cd5f5bSJoe Loser static_assert(std::ranges::view<ForwardRange>);
775671ff20Szoecarver
785671ff20Szoecarver struct MoveOnlyForwardRange : std::ranges::view_interface<MoveOnlyForwardRange> {
795671ff20Szoecarver int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
805671ff20Szoecarver MoveOnlyForwardRange(MoveOnlyForwardRange const&) = delete;
815671ff20Szoecarver MoveOnlyForwardRange(MoveOnlyForwardRange &&) = default;
82c3cd5f5bSJoe Loser MoveOnlyForwardRange& operator=(MoveOnlyForwardRange &&) = default;
835671ff20Szoecarver MoveOnlyForwardRange() = default;
beginMoveOnlyForwardRange845671ff20Szoecarver constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
endMoveOnlyForwardRange855671ff20Szoecarver constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }
865671ff20Szoecarver };
87c3cd5f5bSJoe Loser static_assert(std::ranges::view<MoveOnlyForwardRange>);
885671ff20Szoecarver
892513b790SJoe Loser struct MI : std::ranges::view_interface<InputRange>,
902513b790SJoe Loser std::ranges::view_interface<MoveOnlyForwardRange> {
912513b790SJoe Loser };
922513b790SJoe Loser static_assert(!std::ranges::view<MI>);
932513b790SJoe Loser
945671ff20Szoecarver struct EmptyIsTrue : std::ranges::view_interface<EmptyIsTrue> {
955671ff20Szoecarver int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginEmptyIsTrue965671ff20Szoecarver constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
endEmptyIsTrue975671ff20Szoecarver constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }
emptyEmptyIsTrue985671ff20Szoecarver constexpr bool empty() const { return true; }
995671ff20Szoecarver };
100c3cd5f5bSJoe Loser static_assert(std::ranges::view<EmptyIsTrue>);
1015671ff20Szoecarver
1025671ff20Szoecarver struct SizeIsTen : std::ranges::view_interface<SizeIsTen> {
1035671ff20Szoecarver int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginSizeIsTen1045671ff20Szoecarver constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
endSizeIsTen1055671ff20Szoecarver constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }
sizeSizeIsTen106fb855eb9SMark de Wever constexpr std::size_t size() const { return 10; }
1075671ff20Szoecarver };
108c3cd5f5bSJoe Loser static_assert(std::ranges::view<SizeIsTen>);
1095671ff20Szoecarver
1105671ff20Szoecarver using RAIter = random_access_iterator<int*>;
1115671ff20Szoecarver
1125671ff20Szoecarver struct RARange : std::ranges::view_interface<RARange> {
1135671ff20Szoecarver int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginRARange1145671ff20Szoecarver constexpr RAIter begin() const { return RAIter(const_cast<int*>(buff)); }
endRARange1155671ff20Szoecarver constexpr RAIter end() const { return RAIter(const_cast<int*>(buff) + 8); }
1165671ff20Szoecarver };
117c3cd5f5bSJoe Loser static_assert(std::ranges::view<RARange>);
1185671ff20Szoecarver
1195671ff20Szoecarver using ContIter = contiguous_iterator<const int*>;
1205671ff20Szoecarver
1215671ff20Szoecarver struct ContRange : std::ranges::view_interface<ContRange> {
1225671ff20Szoecarver int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginContRange1235671ff20Szoecarver constexpr ContIter begin() const { return ContIter(buff); }
endContRange1245671ff20Szoecarver constexpr ContIter end() const { return ContIter(buff + 8); }
1255671ff20Szoecarver };
126c3cd5f5bSJoe Loser static_assert(std::ranges::view<ContRange>);
1275671ff20Szoecarver
1285671ff20Szoecarver struct DataIsNull : std::ranges::view_interface<DataIsNull> {
1295671ff20Szoecarver int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginDataIsNull1305671ff20Szoecarver constexpr ContIter begin() const { return ContIter(buff); }
endDataIsNull1315671ff20Szoecarver constexpr ContIter end() const { return ContIter(buff + 8); }
dataDataIsNull1325671ff20Szoecarver constexpr const int *data() const { return nullptr; }
1335671ff20Szoecarver };
134c3cd5f5bSJoe Loser static_assert(std::ranges::view<DataIsNull>);
1355671ff20Szoecarver
1367bdf4165SArthur O'Dwyer struct BoolConvertibleComparison : std::ranges::view_interface<BoolConvertibleComparison> {
1375671ff20Szoecarver struct ResultType {
1385671ff20Szoecarver bool value;
operator boolBoolConvertibleComparison::ResultType1397bdf4165SArthur O'Dwyer constexpr operator bool() const { return value; }
1405671ff20Szoecarver };
1415671ff20Szoecarver
1425671ff20Szoecarver struct SentinelType {
143389e749cSArthur O'Dwyer int *base_;
1447bdf4165SArthur O'Dwyer explicit SentinelType() = default;
SentinelTypeBoolConvertibleComparison::SentinelType1457bdf4165SArthur O'Dwyer constexpr explicit SentinelType(int *base) : base_(base) {}
operator ==BoolConvertibleComparison1465f26d863SMark de Wever friend constexpr ResultType operator==(ForwardIter const& iter, SentinelType const& sent) noexcept { return {base(iter) == sent.base_}; }
operator ==BoolConvertibleComparison1475f26d863SMark de Wever friend constexpr ResultType operator==(SentinelType const& sent, ForwardIter const& iter) noexcept { return {base(iter) == sent.base_}; }
operator !=BoolConvertibleComparison1485f26d863SMark de Wever friend constexpr ResultType operator!=(ForwardIter const& iter, SentinelType const& sent) noexcept { return {base(iter) != sent.base_}; }
operator !=BoolConvertibleComparison1495f26d863SMark de Wever friend constexpr ResultType operator!=(SentinelType const& sent, ForwardIter const& iter) noexcept { return {base(iter) != sent.base_}; }
1505671ff20Szoecarver };
1515671ff20Szoecarver
1525671ff20Szoecarver int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginBoolConvertibleComparison1537bdf4165SArthur O'Dwyer constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
endBoolConvertibleComparison1547bdf4165SArthur O'Dwyer constexpr SentinelType end() const { return SentinelType(const_cast<int*>(buff) + 8); }
1555671ff20Szoecarver };
1567bdf4165SArthur O'Dwyer static_assert(std::ranges::view<BoolConvertibleComparison>);
1575671ff20Szoecarver
1585671ff20Szoecarver template<class T>
1595671ff20Szoecarver concept EmptyInvocable = requires (T const& obj) { obj.empty(); };
1605671ff20Szoecarver
1615671ff20Szoecarver template<class T>
1625671ff20Szoecarver concept BoolOpInvocable = requires (T const& obj) { bool(obj); };
1635671ff20Szoecarver
testEmpty()1645671ff20Szoecarver constexpr bool testEmpty() {
1655671ff20Szoecarver static_assert(!EmptyInvocable<InputRange>);
166*cf09b7deSXiaoyang Liu // LWG 3715: `view_interface::empty` is overconstrained
167*cf09b7deSXiaoyang Liu static_assert(EmptyInvocable<SizedInputRange>);
1685671ff20Szoecarver static_assert( EmptyInvocable<ForwardRange>);
1695671ff20Szoecarver
1705671ff20Szoecarver static_assert(!BoolOpInvocable<InputRange>);
171*cf09b7deSXiaoyang Liu static_assert(BoolOpInvocable<SizedInputRange>);
1725671ff20Szoecarver static_assert( BoolOpInvocable<ForwardRange>);
1735671ff20Szoecarver
174*cf09b7deSXiaoyang Liu SizedInputRange sizedInputRange;
175*cf09b7deSXiaoyang Liu assert(!sizedInputRange.empty());
176*cf09b7deSXiaoyang Liu assert(!static_cast<SizedInputRange const&>(sizedInputRange).empty());
177*cf09b7deSXiaoyang Liu
178*cf09b7deSXiaoyang Liu assert(sizedInputRange);
179*cf09b7deSXiaoyang Liu assert(static_cast<SizedInputRange const&>(sizedInputRange));
180*cf09b7deSXiaoyang Liu
181*cf09b7deSXiaoyang Liu assert(!std::ranges::empty(sizedInputRange));
182*cf09b7deSXiaoyang Liu assert(!std::ranges::empty(static_cast<SizedInputRange const&>(sizedInputRange)));
183*cf09b7deSXiaoyang Liu
1845671ff20Szoecarver ForwardRange forwardRange;
1855671ff20Szoecarver assert(!forwardRange.empty());
1865671ff20Szoecarver assert(!static_cast<ForwardRange const&>(forwardRange).empty());
1875671ff20Szoecarver
1885671ff20Szoecarver assert(forwardRange);
1895671ff20Szoecarver assert(static_cast<ForwardRange const&>(forwardRange));
1905671ff20Szoecarver
1915671ff20Szoecarver assert(!std::ranges::empty(forwardRange));
1925671ff20Szoecarver assert(!std::ranges::empty(static_cast<ForwardRange const&>(forwardRange)));
1935671ff20Szoecarver
1945671ff20Szoecarver EmptyIsTrue emptyTrue;
1955671ff20Szoecarver assert(emptyTrue.empty());
1965671ff20Szoecarver assert(static_cast<EmptyIsTrue const&>(emptyTrue).empty());
1975671ff20Szoecarver assert(!emptyTrue.std::ranges::view_interface<EmptyIsTrue>::empty());
1985671ff20Szoecarver
1995671ff20Szoecarver assert(!emptyTrue);
2005671ff20Szoecarver assert(!static_cast<EmptyIsTrue const&>(emptyTrue));
2015671ff20Szoecarver assert(!emptyTrue.std::ranges::view_interface<EmptyIsTrue>::operator bool());
2025671ff20Szoecarver
2035671ff20Szoecarver assert(std::ranges::empty(emptyTrue));
2045671ff20Szoecarver assert(std::ranges::empty(static_cast<EmptyIsTrue const&>(emptyTrue)));
2055671ff20Szoecarver
2065671ff20Szoecarver // Try calling empty on an rvalue.
2075671ff20Szoecarver MoveOnlyForwardRange moveOnly;
2085671ff20Szoecarver assert(!std::move(moveOnly).empty());
2095671ff20Szoecarver
2107bdf4165SArthur O'Dwyer BoolConvertibleComparison boolConv;
2117bdf4165SArthur O'Dwyer ASSERT_NOT_NOEXCEPT(boolConv.empty());
2125671ff20Szoecarver
2135671ff20Szoecarver assert(!boolConv.empty());
2147bdf4165SArthur O'Dwyer assert(!static_cast<const BoolConvertibleComparison&>(boolConv).empty());
2155671ff20Szoecarver
2165671ff20Szoecarver assert(boolConv);
2177bdf4165SArthur O'Dwyer assert(static_cast<const BoolConvertibleComparison&>(boolConv));
2185671ff20Szoecarver
2195671ff20Szoecarver assert(!std::ranges::empty(boolConv));
2207bdf4165SArthur O'Dwyer assert(!std::ranges::empty(static_cast<const BoolConvertibleComparison&>(boolConv)));
2215671ff20Szoecarver
2225671ff20Szoecarver return true;
2235671ff20Szoecarver }
2245671ff20Szoecarver
2255671ff20Szoecarver template<class T>
2265671ff20Szoecarver concept DataInvocable = requires (T const& obj) { obj.data(); };
2275671ff20Szoecarver
testData()2285671ff20Szoecarver constexpr bool testData() {
2295671ff20Szoecarver static_assert(!DataInvocable<ForwardRange>);
2305671ff20Szoecarver static_assert( DataInvocable<ContRange>);
2315671ff20Szoecarver
2325671ff20Szoecarver ContRange contiguous;
2335671ff20Szoecarver assert(contiguous.data() == contiguous.buff);
2345671ff20Szoecarver assert(static_cast<ContRange const&>(contiguous).data() == contiguous.buff);
2355671ff20Szoecarver
2365671ff20Szoecarver assert(std::ranges::data(contiguous) == contiguous.buff);
2375671ff20Szoecarver assert(std::ranges::data(static_cast<ContRange const&>(contiguous)) == contiguous.buff);
2385671ff20Szoecarver
2395671ff20Szoecarver DataIsNull dataNull;
2405671ff20Szoecarver assert(dataNull.data() == nullptr);
2415671ff20Szoecarver assert(static_cast<DataIsNull const&>(dataNull).data() == nullptr);
2425671ff20Szoecarver assert(dataNull.std::ranges::view_interface<DataIsNull>::data() == dataNull.buff);
2435671ff20Szoecarver
2445671ff20Szoecarver assert(std::ranges::data(dataNull) == nullptr);
2455671ff20Szoecarver assert(std::ranges::data(static_cast<DataIsNull const&>(dataNull)) == nullptr);
2465671ff20Szoecarver
2475671ff20Szoecarver return true;
2485671ff20Szoecarver }
2495671ff20Szoecarver
2505671ff20Szoecarver template<class T>
2515671ff20Szoecarver concept SizeInvocable = requires (T const& obj) { obj.size(); };
2525671ff20Szoecarver
testSize()2535671ff20Szoecarver constexpr bool testSize() {
2545671ff20Szoecarver static_assert(!SizeInvocable<InputRange>);
2555671ff20Szoecarver static_assert(!SizeInvocable<NotSizedSentinel>);
2565671ff20Szoecarver static_assert( SizeInvocable<ForwardRange>);
2575671ff20Szoecarver
25817e6bd80SKonstantin Varlamov // Test the test.
25917e6bd80SKonstantin Varlamov static_assert(std::same_as<decltype(std::declval<ForwardIter>() - std::declval<ForwardIter>()), std::ptrdiff_t>);
26017e6bd80SKonstantin Varlamov using UnsignedSize = std::make_unsigned_t<std::ptrdiff_t>;
26117e6bd80SKonstantin Varlamov using SignedSize = std::common_type_t<std::ptrdiff_t, std::make_signed_t<UnsignedSize>>;
2625671ff20Szoecarver ForwardRange forwardRange;
2635671ff20Szoecarver assert(forwardRange.size() == 8);
2645671ff20Szoecarver assert(static_cast<ForwardRange const&>(forwardRange).size() == 8);
2655671ff20Szoecarver
2665671ff20Szoecarver assert(std::ranges::size(forwardRange) == 8);
26717e6bd80SKonstantin Varlamov static_assert(std::same_as<decltype(std::ranges::size(std::declval<ForwardRange>())), UnsignedSize>);
268c45f382aSIgor Zhukov static_assert(std::same_as<decltype(std::ranges::ssize(std::declval<ForwardRange>())), SignedSize>);
269c45f382aSIgor Zhukov
2705671ff20Szoecarver assert(std::ranges::size(static_cast<ForwardRange const&>(forwardRange)) == 8);
27117e6bd80SKonstantin Varlamov static_assert(std::same_as<decltype(std::ranges::size(std::declval<ForwardRange const>())), UnsignedSize>);
272c45f382aSIgor Zhukov static_assert(std::same_as<decltype(std::ranges::ssize(std::declval<ForwardRange const>())), SignedSize>);
2735671ff20Szoecarver
2745671ff20Szoecarver SizeIsTen sizeTen;
2755671ff20Szoecarver assert(sizeTen.size() == 10);
2765671ff20Szoecarver assert(static_cast<SizeIsTen const&>(sizeTen).size() == 10);
2775671ff20Szoecarver assert(sizeTen.std::ranges::view_interface<SizeIsTen>::size() == 8);
2785671ff20Szoecarver
2795671ff20Szoecarver assert(std::ranges::size(sizeTen) == 10);
2805671ff20Szoecarver assert(std::ranges::size(static_cast<SizeIsTen const&>(sizeTen)) == 10);
2815671ff20Szoecarver
2825671ff20Szoecarver return true;
2835671ff20Szoecarver }
2845671ff20Szoecarver
2855671ff20Szoecarver template<class T>
286fb855eb9SMark de Wever concept SubscriptInvocable = requires (T const& obj, std::size_t n) { obj[n]; };
2875671ff20Szoecarver
testSubscript()2885671ff20Szoecarver constexpr bool testSubscript() {
2895671ff20Szoecarver static_assert(!SubscriptInvocable<ForwardRange>);
2905671ff20Szoecarver static_assert( SubscriptInvocable<RARange>);
2915671ff20Szoecarver
2925671ff20Szoecarver RARange randomAccess;
2935671ff20Szoecarver assert(randomAccess[2] == 2);
2945671ff20Szoecarver assert(static_cast<RARange const&>(randomAccess)[2] == 2);
2955671ff20Szoecarver randomAccess[2] = 3;
2965671ff20Szoecarver assert(randomAccess[2] == 3);
2975671ff20Szoecarver
2985671ff20Szoecarver return true;
2995671ff20Szoecarver }
3005671ff20Szoecarver
3015671ff20Szoecarver template<class T>
3025671ff20Szoecarver concept FrontInvocable = requires (T const& obj) { obj.front(); };
3035671ff20Szoecarver
3045671ff20Szoecarver template<class T>
3055671ff20Szoecarver concept BackInvocable = requires (T const& obj) { obj.back(); };
3065671ff20Szoecarver
testFrontBack()3075671ff20Szoecarver constexpr bool testFrontBack() {
3085671ff20Szoecarver static_assert(!FrontInvocable<InputRange>);
3095671ff20Szoecarver static_assert( FrontInvocable<ForwardRange>);
3105671ff20Szoecarver static_assert(!BackInvocable<ForwardRange>);
3115671ff20Szoecarver static_assert( BackInvocable<RARange>);
3125671ff20Szoecarver
3135671ff20Szoecarver ForwardRange forwardRange;
3145671ff20Szoecarver assert(forwardRange.front() == 0);
3155671ff20Szoecarver assert(static_cast<ForwardRange const&>(forwardRange).front() == 0);
3165671ff20Szoecarver forwardRange.front() = 2;
3175671ff20Szoecarver assert(forwardRange.front() == 2);
3185671ff20Szoecarver
3195671ff20Szoecarver RARange randomAccess;
3205671ff20Szoecarver assert(randomAccess.front() == 0);
3215671ff20Szoecarver assert(static_cast<RARange const&>(randomAccess).front() == 0);
3225671ff20Szoecarver randomAccess.front() = 2;
3235671ff20Szoecarver assert(randomAccess.front() == 2);
3245671ff20Szoecarver
3255671ff20Szoecarver assert(randomAccess.back() == 7);
3265671ff20Szoecarver assert(static_cast<RARange const&>(randomAccess).back() == 7);
3275671ff20Szoecarver randomAccess.back() = 2;
3285671ff20Szoecarver assert(randomAccess.back() == 2);
3295671ff20Szoecarver
3305671ff20Szoecarver return true;
3315671ff20Szoecarver }
3325671ff20Szoecarver
3332513b790SJoe Loser struct V1 : std::ranges::view_interface<V1> { };
3342513b790SJoe Loser struct V2 : std::ranges::view_interface<V2> { V1 base_; };
3352513b790SJoe Loser static_assert(sizeof(V2) == sizeof(V1));
3362513b790SJoe Loser
main(int,char **)3375671ff20Szoecarver int main(int, char**) {
3385671ff20Szoecarver testEmpty();
3395671ff20Szoecarver static_assert(testEmpty());
3405671ff20Szoecarver
3415671ff20Szoecarver testData();
3425671ff20Szoecarver static_assert(testData());
3435671ff20Szoecarver
3445671ff20Szoecarver testSize();
3455671ff20Szoecarver static_assert(testSize());
3465671ff20Szoecarver
3475671ff20Szoecarver testSubscript();
3485671ff20Szoecarver static_assert(testSubscript());
3495671ff20Szoecarver
3505671ff20Szoecarver testFrontBack();
3515671ff20Szoecarver static_assert(testFrontBack());
3525671ff20Szoecarver
3535671ff20Szoecarver return 0;
3545671ff20Szoecarver }
355