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