xref: /aosp_15_r20/external/cronet/base/ranges/ranges.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_RANGES_RANGES_H_
6 #define BASE_RANGES_RANGES_H_
7 
8 #include <array>
9 #include <iterator>
10 #include <type_traits>
11 #include <utility>
12 
13 #include "base/template_util.h"
14 
15 namespace base {
16 
17 namespace internal {
18 
19 // Overload for C array.
20 template <typename T, size_t N>
begin(T (& array)[N],priority_tag<2>)21 constexpr T* begin(T (&array)[N], priority_tag<2>) {
22   return array;
23 }
24 
25 // Generic container overload.
26 template <typename Range>
27 constexpr auto begin(Range&& range, priority_tag<1>)
28     -> decltype(std::forward<Range>(range).begin()) {
29   return std::forward<Range>(range).begin();
30 }
31 
32 // Overload for free begin() function.
33 template <typename Range>
34 constexpr auto begin(Range&& range, priority_tag<0>)
35     -> decltype(begin(std::forward<Range>(range))) {
36   return begin(std::forward<Range>(range));
37 }
38 
39 // Overload for C array.
40 template <typename T, size_t N>
end(T (& array)[N],priority_tag<2>)41 constexpr T* end(T (&array)[N], priority_tag<2>) {
42   return array + N;
43 }
44 
45 // Generic container overload.
46 template <typename Range>
47 constexpr auto end(Range&& range, priority_tag<1>)
48     -> decltype(std::forward<Range>(range).end()) {
49   return std::forward<Range>(range).end();
50 }
51 
52 // Overload for free end() function.
53 template <typename Range>
54 constexpr auto end(Range&& range, priority_tag<0>)
55     -> decltype(end(std::forward<Range>(range))) {
56   return end(std::forward<Range>(range));
57 }
58 
59 }  // namespace internal
60 
61 namespace ranges {
62 
63 // Simplified implementation of C++20's std::ranges::begin.
64 // As opposed to std::ranges::begin, this implementation does does not check
65 // whether begin() returns an iterator and does not inhibit ADL.
66 //
67 // The trailing return type and dispatch to the internal implementation is
68 // necessary to be SFINAE friendly.
69 //
70 // Reference: https://wg21.link/range.access.begin
71 template <typename Range>
72 constexpr auto begin(Range&& range) noexcept
73     -> decltype(internal::begin(std::forward<Range>(range),
74                                 internal::priority_tag<2>())) {
75   return internal::begin(std::forward<Range>(range),
76                          internal::priority_tag<2>());
77 }
78 
79 // Simplified implementation of C++20's std::ranges::end.
80 // As opposed to std::ranges::end, this implementation does does not check
81 // whether end() returns an iterator and does not inhibit ADL.
82 //
83 // The trailing return type and dispatch to the internal implementation is
84 // necessary to be SFINAE friendly.
85 //
86 // Reference: - https://wg21.link/range.access.end
87 template <typename Range>
88 constexpr auto end(Range&& range) noexcept
89     -> decltype(internal::end(std::forward<Range>(range),
90                               internal::priority_tag<2>())) {
91   return internal::end(std::forward<Range>(range), internal::priority_tag<2>());
92 }
93 
94 // Implementation of C++20's std::ranges::iterator_t.
95 //
96 // Reference: https://wg21.link/ranges.syn#:~:text=iterator_t
97 template <typename Range>
98 using iterator_t = decltype(ranges::begin(std::declval<Range&>()));
99 
100 // Implementation of C++20's std::ranges::range_value_t.
101 //
102 // Reference: https://wg21.link/ranges.syn#:~:text=range_value_t
103 template <typename Range>
104 using range_value_t = std::iter_value_t<iterator_t<Range>>;
105 
106 }  // namespace ranges
107 
108 }  // namespace base
109 
110 #endif  // BASE_RANGES_RANGES_H_
111