1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 // UNSUPPORTED: libcpp-no-concepts
11 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
12 
13 // constexpr auto size() requires sized_range<V>
14 // constexpr auto size() const requires sized_range<const V>
15 
16 #include <ranges>
17 #include <cassert>
18 
19 #include "test_iterators.h"
20 #include "test_range.h"
21 
22 struct CopyableView : std::ranges::view_base {
23   int *ptr_;
24   constexpr CopyableView(int* ptr) : ptr_(ptr) {}
25   friend constexpr int* begin(CopyableView& view) { return view.ptr_; }
26   friend constexpr int* begin(CopyableView const& view) { return view.ptr_; }
27   friend constexpr sentinel_wrapper<int*> end(CopyableView& view) {
28     return sentinel_wrapper<int*>{view.ptr_ + 8};
29   }
30   friend constexpr sentinel_wrapper<int*> end(CopyableView const& view) {
31     return sentinel_wrapper<int*>{view.ptr_ + 8};
32   }
33 };
34 
35 using ForwardIter = forward_iterator<int*>;
36 struct SizedForwardView : std::ranges::view_base {
37   int *ptr_;
38   constexpr SizedForwardView(int* ptr) : ptr_(ptr) {}
39   friend constexpr ForwardIter begin(SizedForwardView& view) { return ForwardIter(view.ptr_); }
40   friend constexpr ForwardIter begin(SizedForwardView const& view) { return ForwardIter(view.ptr_); }
41   friend constexpr sentinel_wrapper<ForwardIter> end(SizedForwardView& view) {
42     return sentinel_wrapper<ForwardIter>{ForwardIter(view.ptr_ + 8)};
43   }
44   friend constexpr sentinel_wrapper<ForwardIter> end(SizedForwardView const& view) {
45     return sentinel_wrapper<ForwardIter>{ForwardIter(view.ptr_ + 8)};
46   }
47 };
48 
49 constexpr auto operator-(sentinel_wrapper<ForwardIter> sent, ForwardIter iter) {
50   return sent.base().base() - iter.base();
51 }
52 constexpr auto operator-(ForwardIter iter, sentinel_wrapper<ForwardIter> sent) {
53   return iter.base() - sent.base().base();
54 }
55 
56 template<class T>
57 concept SizeEnabled = requires(const std::ranges::common_view<T>& comm) {
58   comm.size();
59 };
60 
61 constexpr bool test() {
62   int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
63 
64   {
65     static_assert( SizeEnabled<SizedForwardView>);
66     static_assert(!SizeEnabled<CopyableView>);
67   }
68 
69   {
70     std::ranges::common_view<SizedForwardView> common(SizedForwardView{buffer});
71     assert(common.size() == 8);
72   }
73 
74   {
75     const std::ranges::common_view<SizedForwardView> common(SizedForwardView{buffer});
76     assert(common.size() == 8);
77   }
78 
79   return true;
80 }
81 
82 int main(int, char**) {
83   test();
84   static_assert(test());
85 
86   return 0;
87 }
88