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