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