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 
11 // template<range R>
12 //   constexpr range_difference_t<R> ranges::distance(R&& r);
13 
14 #include <iterator>
15 #include <cassert>
16 #include <ranges>
17 
18 #include "test_iterators.h"
19 #include "test_macros.h"
20 
21 template<class It, class Sent>
22 constexpr void test_ordinary() {
23   struct R {
24     mutable int a[3] = {1, 2, 3};
25     constexpr It begin() const { return It(a); }
26     constexpr Sent end() const { return Sent(It(a + 3)); }
27   };
28   R r;
29   assert(std::ranges::distance(r) == 3);
30   assert(std::ranges::distance(static_cast<R&&>(r)) == 3);
31   assert(std::ranges::distance(static_cast<const R&>(r)) == 3);
32   assert(std::ranges::distance(static_cast<const R&&>(r)) == 3);
33   ASSERT_SAME_TYPE(decltype(std::ranges::distance(r)), std::ranges::range_difference_t<R>);
34 }
35 
36 constexpr bool test() {
37   {
38     using R = int[3];
39     int a[] = {1, 2, 3};
40     assert(std::ranges::distance(static_cast<R&>(a)) == 3);
41     assert(std::ranges::distance(static_cast<R&&>(a)) == 3);
42     assert(std::ranges::distance(static_cast<const R&>(a)) == 3);
43     assert(std::ranges::distance(static_cast<const R&&>(a)) == 3);
44     ASSERT_SAME_TYPE(decltype(std::ranges::distance(a)), std::ptrdiff_t);
45     ASSERT_SAME_TYPE(decltype(std::ranges::distance(a)), std::ranges::range_difference_t<R>);
46   }
47   {
48     // Unsized range, non-copyable iterator type, rvalue-ref-qualified begin()
49     using It = cpp20_input_iterator<int*>;
50     using Sent = sentinel_wrapper<cpp20_input_iterator<int*>>;
51     using R = std::ranges::subrange<It, Sent, std::ranges::subrange_kind::unsized>;
52 
53     int a[] = {1, 2, 3};
54     {
55       auto r = R(It(a), Sent(It(a + 3)));
56       assert(std::ranges::distance(r) == 3);
57     }
58     {
59       auto r = R(It(a), Sent(It(a + 3)));
60       assert(std::ranges::distance(static_cast<R&&>(r)) == 3);
61     }
62     static_assert(!std::is_invocable_v<decltype(std::ranges::distance), const R&>);
63     static_assert(!std::is_invocable_v<decltype(std::ranges::distance), const R&&>);
64   }
65   {
66     // Sized range (unsized sentinel type), non-copyable iterator type, rvalue-ref-qualified begin()
67     using It = cpp20_input_iterator<int*>;
68     using Sent = sentinel_wrapper<cpp20_input_iterator<int*>>;
69     using R = std::ranges::subrange<It, Sent, std::ranges::subrange_kind::sized>;
70 
71     int a[] = {1, 2, 3};
72     {
73       auto r = R(It(a), Sent(It(a + 3)), 3);
74       assert(std::ranges::distance(r) == 3);
75     }
76     {
77       auto r = R(It(a), Sent(It(a + 3)), 3);
78       assert(std::ranges::distance(static_cast<R&&>(r)) == 3);
79     }
80     static_assert(!std::is_invocable_v<decltype(std::ranges::distance), const R&>);
81     static_assert(!std::is_invocable_v<decltype(std::ranges::distance), const R&&>);
82   }
83   {
84     // Sized range (sized sentinel type), non-copyable iterator type
85     test_ordinary<cpp20_input_iterator<int*>, sized_sentinel<cpp20_input_iterator<int*>>>();
86   }
87   test_ordinary<cpp17_input_iterator<int*>, sentinel_wrapper<cpp17_input_iterator<int*>>>();
88   test_ordinary<cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>>();
89   test_ordinary<cpp17_output_iterator<int*>, sentinel_wrapper<cpp17_output_iterator<int*>>>();
90   test_ordinary<forward_iterator<int*>, sentinel_wrapper<forward_iterator<int*>>>();
91   test_ordinary<bidirectional_iterator<int*>, sentinel_wrapper<bidirectional_iterator<int*>>>();
92   test_ordinary<random_access_iterator<int*>, sentinel_wrapper<random_access_iterator<int*>>>();
93   test_ordinary<contiguous_iterator<int*>, sentinel_wrapper<contiguous_iterator<int*>>>();
94   test_ordinary<int*, sentinel_wrapper<int*>>();
95 
96   test_ordinary<cpp17_input_iterator<int*>, sized_sentinel<cpp17_input_iterator<int*>>>();
97   test_ordinary<cpp20_input_iterator<int*>, sized_sentinel<cpp20_input_iterator<int*>>>();
98   test_ordinary<cpp17_output_iterator<int*>, sized_sentinel<cpp17_output_iterator<int*>>>();
99   test_ordinary<forward_iterator<int*>, sized_sentinel<forward_iterator<int*>>>();
100   test_ordinary<bidirectional_iterator<int*>, sized_sentinel<bidirectional_iterator<int*>>>();
101   test_ordinary<random_access_iterator<int*>, sized_sentinel<random_access_iterator<int*>>>();
102   test_ordinary<contiguous_iterator<int*>, sized_sentinel<contiguous_iterator<int*>>>();
103   test_ordinary<int*, sized_sentinel<int*>>();
104   test_ordinary<int*, int*>();
105 
106   // Calling it on a non-range isn't allowed.
107   static_assert(!std::is_invocable_v<decltype(std::ranges::distance), int>);
108   static_assert(!std::is_invocable_v<decltype(std::ranges::distance), int*>);
109 
110   return true;
111 }
112 
113 int main(int, char**) {
114   test();
115   static_assert(test());
116 
117   return 0;
118 }
119