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
1071909de3SMark de Wever // UNSUPPORTED: libcpp-has-no-incomplete-ranges
115671ff20Szoecarver 
125671ff20Szoecarver // template<class D>
135671ff20Szoecarver //   requires is_class_v<D> && same_as<D, remove_cv_t<D>>
145671ff20Szoecarver // class view_interface;
155671ff20Szoecarver 
165671ff20Szoecarver #include <ranges>
175671ff20Szoecarver 
185671ff20Szoecarver #include <cassert>
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 
425671ff20Szoecarver struct NotSizedSentinel {
43389e749cSArthur O'Dwyer   using value_type = int;
44389e749cSArthur O'Dwyer   using difference_type = std::ptrdiff_t;
455671ff20Szoecarver   using iterator_concept = std::forward_iterator_tag;
465671ff20Szoecarver 
47389e749cSArthur O'Dwyer   explicit NotSizedSentinel() = default;
48389e749cSArthur O'Dwyer   explicit NotSizedSentinel(int*);
49389e749cSArthur O'Dwyer   int& operator*() const;
505671ff20Szoecarver   NotSizedSentinel& operator++();
515671ff20Szoecarver   NotSizedSentinel operator++(int);
525671ff20Szoecarver   bool operator==(NotSizedSentinel const&) const;
535671ff20Szoecarver };
545671ff20Szoecarver static_assert(std::forward_iterator<NotSizedSentinel>);
555671ff20Szoecarver 
565671ff20Szoecarver using ForwardIter = forward_iterator<int*>;
575671ff20Szoecarver 
585671ff20Szoecarver // So that we conform to sized_sentinel_for.
operator -(const ForwardIter & x,const ForwardIter & y)595671ff20Szoecarver constexpr std::ptrdiff_t operator-(const ForwardIter& x, const ForwardIter& y) {
60*5f26d863SMark de Wever     return base(x) - base(y);
615671ff20Szoecarver }
625671ff20Szoecarver 
635671ff20Szoecarver struct ForwardRange : std::ranges::view_interface<ForwardRange> {
645671ff20Szoecarver   int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginForwardRange655671ff20Szoecarver   constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
endForwardRange665671ff20Szoecarver   constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }
675671ff20Szoecarver };
68c3cd5f5bSJoe Loser static_assert(std::ranges::view<ForwardRange>);
695671ff20Szoecarver 
705671ff20Szoecarver struct MoveOnlyForwardRange : std::ranges::view_interface<MoveOnlyForwardRange> {
715671ff20Szoecarver   int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
725671ff20Szoecarver   MoveOnlyForwardRange(MoveOnlyForwardRange const&) = delete;
735671ff20Szoecarver   MoveOnlyForwardRange(MoveOnlyForwardRange &&) = default;
74c3cd5f5bSJoe Loser   MoveOnlyForwardRange& operator=(MoveOnlyForwardRange &&) = default;
755671ff20Szoecarver   MoveOnlyForwardRange() = default;
beginMoveOnlyForwardRange765671ff20Szoecarver   constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
endMoveOnlyForwardRange775671ff20Szoecarver   constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }
785671ff20Szoecarver };
79c3cd5f5bSJoe Loser static_assert(std::ranges::view<MoveOnlyForwardRange>);
805671ff20Szoecarver 
812513b790SJoe Loser struct MI : std::ranges::view_interface<InputRange>,
822513b790SJoe Loser             std::ranges::view_interface<MoveOnlyForwardRange> {
832513b790SJoe Loser };
842513b790SJoe Loser static_assert(!std::ranges::view<MI>);
852513b790SJoe Loser 
865671ff20Szoecarver struct EmptyIsTrue : std::ranges::view_interface<EmptyIsTrue> {
875671ff20Szoecarver   int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginEmptyIsTrue885671ff20Szoecarver   constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
endEmptyIsTrue895671ff20Szoecarver   constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }
emptyEmptyIsTrue905671ff20Szoecarver   constexpr bool empty() const { return true; }
915671ff20Szoecarver };
92c3cd5f5bSJoe Loser static_assert(std::ranges::view<EmptyIsTrue>);
935671ff20Szoecarver 
945671ff20Szoecarver struct SizeIsTen : std::ranges::view_interface<SizeIsTen> {
955671ff20Szoecarver   int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginSizeIsTen965671ff20Szoecarver   constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
endSizeIsTen975671ff20Szoecarver   constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }
sizeSizeIsTen985671ff20Szoecarver   constexpr size_t size() const { return 10; }
995671ff20Szoecarver };
100c3cd5f5bSJoe Loser static_assert(std::ranges::view<SizeIsTen>);
1015671ff20Szoecarver 
1025671ff20Szoecarver using RAIter = random_access_iterator<int*>;
1035671ff20Szoecarver 
1045671ff20Szoecarver struct RARange : std::ranges::view_interface<RARange> {
1055671ff20Szoecarver   int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginRARange1065671ff20Szoecarver   constexpr RAIter begin() const { return RAIter(const_cast<int*>(buff)); }
endRARange1075671ff20Szoecarver   constexpr RAIter end() const { return RAIter(const_cast<int*>(buff) + 8); }
1085671ff20Szoecarver };
109c3cd5f5bSJoe Loser static_assert(std::ranges::view<RARange>);
1105671ff20Szoecarver 
1115671ff20Szoecarver using ContIter = contiguous_iterator<const int*>;
1125671ff20Szoecarver 
1135671ff20Szoecarver struct ContRange : std::ranges::view_interface<ContRange> {
1145671ff20Szoecarver   int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginContRange1155671ff20Szoecarver   constexpr ContIter begin() const { return ContIter(buff); }
endContRange1165671ff20Szoecarver   constexpr ContIter end() const { return ContIter(buff + 8); }
1175671ff20Szoecarver };
118c3cd5f5bSJoe Loser static_assert(std::ranges::view<ContRange>);
1195671ff20Szoecarver 
1205671ff20Szoecarver struct DataIsNull : std::ranges::view_interface<DataIsNull> {
1215671ff20Szoecarver   int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginDataIsNull1225671ff20Szoecarver   constexpr ContIter begin() const { return ContIter(buff); }
endDataIsNull1235671ff20Szoecarver   constexpr ContIter end() const { return ContIter(buff + 8); }
dataDataIsNull1245671ff20Szoecarver   constexpr const int *data() const { return nullptr; }
1255671ff20Szoecarver };
126c3cd5f5bSJoe Loser static_assert(std::ranges::view<DataIsNull>);
1275671ff20Szoecarver 
1287bdf4165SArthur O'Dwyer struct BoolConvertibleComparison : std::ranges::view_interface<BoolConvertibleComparison> {
1295671ff20Szoecarver   struct ResultType {
1305671ff20Szoecarver     bool value;
operator boolBoolConvertibleComparison::ResultType1317bdf4165SArthur O'Dwyer     constexpr operator bool() const { return value; }
1325671ff20Szoecarver   };
1335671ff20Szoecarver 
1345671ff20Szoecarver   struct SentinelType {
135389e749cSArthur O'Dwyer     int *base_;
1367bdf4165SArthur O'Dwyer     explicit SentinelType() = default;
SentinelTypeBoolConvertibleComparison::SentinelType1377bdf4165SArthur O'Dwyer     constexpr explicit SentinelType(int *base) : base_(base) {}
operator ==BoolConvertibleComparison138*5f26d863SMark de Wever     friend constexpr ResultType operator==(ForwardIter const& iter, SentinelType const& sent) noexcept { return {base(iter) == sent.base_}; }
operator ==BoolConvertibleComparison139*5f26d863SMark de Wever     friend constexpr ResultType operator==(SentinelType const& sent, ForwardIter const& iter) noexcept { return {base(iter) == sent.base_}; }
operator !=BoolConvertibleComparison140*5f26d863SMark de Wever     friend constexpr ResultType operator!=(ForwardIter const& iter, SentinelType const& sent) noexcept { return {base(iter) != sent.base_}; }
operator !=BoolConvertibleComparison141*5f26d863SMark de Wever     friend constexpr ResultType operator!=(SentinelType const& sent, ForwardIter const& iter) noexcept { return {base(iter) != sent.base_}; }
1425671ff20Szoecarver   };
1435671ff20Szoecarver 
1445671ff20Szoecarver   int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
beginBoolConvertibleComparison1457bdf4165SArthur O'Dwyer   constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
endBoolConvertibleComparison1467bdf4165SArthur O'Dwyer   constexpr SentinelType end() const { return SentinelType(const_cast<int*>(buff) + 8); }
1475671ff20Szoecarver };
1487bdf4165SArthur O'Dwyer static_assert(std::ranges::view<BoolConvertibleComparison>);
1495671ff20Szoecarver 
1505671ff20Szoecarver template<class T>
1515671ff20Szoecarver concept EmptyInvocable = requires (T const& obj) { obj.empty(); };
1525671ff20Szoecarver 
1535671ff20Szoecarver template<class T>
1545671ff20Szoecarver concept BoolOpInvocable = requires (T const& obj) { bool(obj); };
1555671ff20Szoecarver 
testEmpty()1565671ff20Szoecarver constexpr bool testEmpty() {
1575671ff20Szoecarver   static_assert(!EmptyInvocable<InputRange>);
1585671ff20Szoecarver   static_assert( EmptyInvocable<ForwardRange>);
1595671ff20Szoecarver 
1605671ff20Szoecarver   static_assert(!BoolOpInvocable<InputRange>);
1615671ff20Szoecarver   static_assert( BoolOpInvocable<ForwardRange>);
1625671ff20Szoecarver 
1635671ff20Szoecarver   ForwardRange forwardRange;
1645671ff20Szoecarver   assert(!forwardRange.empty());
1655671ff20Szoecarver   assert(!static_cast<ForwardRange const&>(forwardRange).empty());
1665671ff20Szoecarver 
1675671ff20Szoecarver   assert(forwardRange);
1685671ff20Szoecarver   assert(static_cast<ForwardRange const&>(forwardRange));
1695671ff20Szoecarver 
1705671ff20Szoecarver   assert(!std::ranges::empty(forwardRange));
1715671ff20Szoecarver   assert(!std::ranges::empty(static_cast<ForwardRange const&>(forwardRange)));
1725671ff20Szoecarver 
1735671ff20Szoecarver   EmptyIsTrue emptyTrue;
1745671ff20Szoecarver   assert(emptyTrue.empty());
1755671ff20Szoecarver   assert(static_cast<EmptyIsTrue const&>(emptyTrue).empty());
1765671ff20Szoecarver   assert(!emptyTrue.std::ranges::view_interface<EmptyIsTrue>::empty());
1775671ff20Szoecarver 
1785671ff20Szoecarver   assert(!emptyTrue);
1795671ff20Szoecarver   assert(!static_cast<EmptyIsTrue const&>(emptyTrue));
1805671ff20Szoecarver   assert(!emptyTrue.std::ranges::view_interface<EmptyIsTrue>::operator bool());
1815671ff20Szoecarver 
1825671ff20Szoecarver   assert(std::ranges::empty(emptyTrue));
1835671ff20Szoecarver   assert(std::ranges::empty(static_cast<EmptyIsTrue const&>(emptyTrue)));
1845671ff20Szoecarver 
1855671ff20Szoecarver   // Try calling empty on an rvalue.
1865671ff20Szoecarver   MoveOnlyForwardRange moveOnly;
1875671ff20Szoecarver   assert(!std::move(moveOnly).empty());
1885671ff20Szoecarver 
1897bdf4165SArthur O'Dwyer   BoolConvertibleComparison boolConv;
1907bdf4165SArthur O'Dwyer   ASSERT_NOT_NOEXCEPT(boolConv.empty());
1915671ff20Szoecarver 
1925671ff20Szoecarver   assert(!boolConv.empty());
1937bdf4165SArthur O'Dwyer   assert(!static_cast<const BoolConvertibleComparison&>(boolConv).empty());
1945671ff20Szoecarver 
1955671ff20Szoecarver   assert(boolConv);
1967bdf4165SArthur O'Dwyer   assert(static_cast<const BoolConvertibleComparison&>(boolConv));
1975671ff20Szoecarver 
1985671ff20Szoecarver   assert(!std::ranges::empty(boolConv));
1997bdf4165SArthur O'Dwyer   assert(!std::ranges::empty(static_cast<const BoolConvertibleComparison&>(boolConv)));
2005671ff20Szoecarver 
2015671ff20Szoecarver   return true;
2025671ff20Szoecarver }
2035671ff20Szoecarver 
2045671ff20Szoecarver template<class T>
2055671ff20Szoecarver concept DataInvocable = requires (T const& obj) { obj.data(); };
2065671ff20Szoecarver 
testData()2075671ff20Szoecarver constexpr bool testData() {
2085671ff20Szoecarver   static_assert(!DataInvocable<ForwardRange>);
2095671ff20Szoecarver   static_assert( DataInvocable<ContRange>);
2105671ff20Szoecarver 
2115671ff20Szoecarver   ContRange contiguous;
2125671ff20Szoecarver   assert(contiguous.data() == contiguous.buff);
2135671ff20Szoecarver   assert(static_cast<ContRange const&>(contiguous).data() == contiguous.buff);
2145671ff20Szoecarver 
2155671ff20Szoecarver   assert(std::ranges::data(contiguous) == contiguous.buff);
2165671ff20Szoecarver   assert(std::ranges::data(static_cast<ContRange const&>(contiguous)) == contiguous.buff);
2175671ff20Szoecarver 
2185671ff20Szoecarver   DataIsNull dataNull;
2195671ff20Szoecarver   assert(dataNull.data() == nullptr);
2205671ff20Szoecarver   assert(static_cast<DataIsNull const&>(dataNull).data() == nullptr);
2215671ff20Szoecarver   assert(dataNull.std::ranges::view_interface<DataIsNull>::data() == dataNull.buff);
2225671ff20Szoecarver 
2235671ff20Szoecarver   assert(std::ranges::data(dataNull) == nullptr);
2245671ff20Szoecarver   assert(std::ranges::data(static_cast<DataIsNull const&>(dataNull)) == nullptr);
2255671ff20Szoecarver 
2265671ff20Szoecarver   return true;
2275671ff20Szoecarver }
2285671ff20Szoecarver 
2295671ff20Szoecarver template<class T>
2305671ff20Szoecarver concept SizeInvocable = requires (T const& obj) { obj.size(); };
2315671ff20Szoecarver 
testSize()2325671ff20Szoecarver constexpr bool testSize() {
2335671ff20Szoecarver   static_assert(!SizeInvocable<InputRange>);
2345671ff20Szoecarver   static_assert(!SizeInvocable<NotSizedSentinel>);
2355671ff20Szoecarver   static_assert( SizeInvocable<ForwardRange>);
2365671ff20Szoecarver 
2375671ff20Szoecarver   ForwardRange forwardRange;
2385671ff20Szoecarver   assert(forwardRange.size() == 8);
2395671ff20Szoecarver   assert(static_cast<ForwardRange const&>(forwardRange).size() == 8);
2405671ff20Szoecarver 
2415671ff20Szoecarver   assert(std::ranges::size(forwardRange) == 8);
2425671ff20Szoecarver   assert(std::ranges::size(static_cast<ForwardRange const&>(forwardRange)) == 8);
2435671ff20Szoecarver 
2445671ff20Szoecarver   SizeIsTen sizeTen;
2455671ff20Szoecarver   assert(sizeTen.size() == 10);
2465671ff20Szoecarver   assert(static_cast<SizeIsTen const&>(sizeTen).size() == 10);
2475671ff20Szoecarver   assert(sizeTen.std::ranges::view_interface<SizeIsTen>::size() == 8);
2485671ff20Szoecarver 
2495671ff20Szoecarver   assert(std::ranges::size(sizeTen) == 10);
2505671ff20Szoecarver   assert(std::ranges::size(static_cast<SizeIsTen const&>(sizeTen)) == 10);
2515671ff20Szoecarver 
2525671ff20Szoecarver   return true;
2535671ff20Szoecarver }
2545671ff20Szoecarver 
2555671ff20Szoecarver template<class T>
2565671ff20Szoecarver concept SubscriptInvocable = requires (T const& obj, size_t n) { obj[n]; };
2575671ff20Szoecarver 
testSubscript()2585671ff20Szoecarver constexpr bool testSubscript() {
2595671ff20Szoecarver   static_assert(!SubscriptInvocable<ForwardRange>);
2605671ff20Szoecarver   static_assert( SubscriptInvocable<RARange>);
2615671ff20Szoecarver 
2625671ff20Szoecarver   RARange randomAccess;
2635671ff20Szoecarver   assert(randomAccess[2] == 2);
2645671ff20Szoecarver   assert(static_cast<RARange const&>(randomAccess)[2] == 2);
2655671ff20Szoecarver   randomAccess[2] = 3;
2665671ff20Szoecarver   assert(randomAccess[2] == 3);
2675671ff20Szoecarver 
2685671ff20Szoecarver   return true;
2695671ff20Szoecarver }
2705671ff20Szoecarver 
2715671ff20Szoecarver template<class T>
2725671ff20Szoecarver concept FrontInvocable = requires (T const& obj) { obj.front(); };
2735671ff20Szoecarver 
2745671ff20Szoecarver template<class T>
2755671ff20Szoecarver concept BackInvocable = requires (T const& obj) { obj.back(); };
2765671ff20Szoecarver 
testFrontBack()2775671ff20Szoecarver constexpr bool testFrontBack() {
2785671ff20Szoecarver   static_assert(!FrontInvocable<InputRange>);
2795671ff20Szoecarver   static_assert( FrontInvocable<ForwardRange>);
2805671ff20Szoecarver   static_assert(!BackInvocable<ForwardRange>);
2815671ff20Szoecarver   static_assert( BackInvocable<RARange>);
2825671ff20Szoecarver 
2835671ff20Szoecarver   ForwardRange forwardRange;
2845671ff20Szoecarver   assert(forwardRange.front() == 0);
2855671ff20Szoecarver   assert(static_cast<ForwardRange const&>(forwardRange).front() == 0);
2865671ff20Szoecarver   forwardRange.front() = 2;
2875671ff20Szoecarver   assert(forwardRange.front() == 2);
2885671ff20Szoecarver 
2895671ff20Szoecarver   RARange randomAccess;
2905671ff20Szoecarver   assert(randomAccess.front() == 0);
2915671ff20Szoecarver   assert(static_cast<RARange const&>(randomAccess).front() == 0);
2925671ff20Szoecarver   randomAccess.front() = 2;
2935671ff20Szoecarver   assert(randomAccess.front() == 2);
2945671ff20Szoecarver 
2955671ff20Szoecarver   assert(randomAccess.back() == 7);
2965671ff20Szoecarver   assert(static_cast<RARange const&>(randomAccess).back() == 7);
2975671ff20Szoecarver   randomAccess.back() = 2;
2985671ff20Szoecarver   assert(randomAccess.back() == 2);
2995671ff20Szoecarver 
3005671ff20Szoecarver   return true;
3015671ff20Szoecarver }
3025671ff20Szoecarver 
3032513b790SJoe Loser struct V1 : std::ranges::view_interface<V1> { };
3042513b790SJoe Loser struct V2 : std::ranges::view_interface<V2> { V1 base_; };
3052513b790SJoe Loser static_assert(sizeof(V2) == sizeof(V1));
3062513b790SJoe Loser 
main(int,char **)3075671ff20Szoecarver int main(int, char**) {
3085671ff20Szoecarver   testEmpty();
3095671ff20Szoecarver   static_assert(testEmpty());
3105671ff20Szoecarver 
3115671ff20Szoecarver   testData();
3125671ff20Szoecarver   static_assert(testData());
3135671ff20Szoecarver 
3145671ff20Szoecarver   testSize();
3155671ff20Szoecarver   static_assert(testSize());
3165671ff20Szoecarver 
3175671ff20Szoecarver   testSubscript();
3185671ff20Szoecarver   static_assert(testSubscript());
3195671ff20Szoecarver 
3205671ff20Szoecarver   testFrontBack();
3215671ff20Szoecarver   static_assert(testFrontBack());
3225671ff20Szoecarver 
3235671ff20Szoecarver   return 0;
3245671ff20Szoecarver }
325