• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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_CONTAINERS_ADAPTERS_INTERNAL_H_
6 #define BASE_CONTAINERS_ADAPTERS_INTERNAL_H_
7 
8 #include <stddef.h>
9 
10 #include <iterator>
11 #include <ranges>
12 #include <utility>
13 
14 #include "base/compiler_specific.h"
15 #include "base/memory/raw_ptr_exclusion.h"
16 
17 namespace base::internal {
18 template <typename Range>
19 class RangeOfRvaluesAdapter;
20 template <typename Range>
21 class ReversedAdapter;
22 }  // namespace base::internal
23 
24 // This is technically correct, but presently always evaluates to false since
25 // `RangeAsRvalues()` bans non-borrowed ranges.
26 template <typename Range>
27 inline constexpr bool std::ranges::enable_borrowed_range<
28     base::internal::RangeOfRvaluesAdapter<Range>> =
29     std::ranges::borrowed_range<Range>;
30 
31 template <typename Range>
32 inline constexpr bool
33     std::ranges::enable_borrowed_range<base::internal::ReversedAdapter<Range>> =
34         std::ranges::borrowed_range<Range>;
35 
36 namespace base::internal {
37 
38 template <typename Range>
39 class RangeOfRvaluesAdapter {
40  public:
RangeOfRvaluesAdapter(Range && range LIFETIME_BOUND)41   explicit RangeOfRvaluesAdapter(Range&& range LIFETIME_BOUND)
42       : range_(std::forward<Range>(range)) {}
43   RangeOfRvaluesAdapter(const RangeOfRvaluesAdapter&) = default;
44   RangeOfRvaluesAdapter& operator=(const RangeOfRvaluesAdapter&) = delete;
45 
size()46   auto size() const
47     requires std::ranges::sized_range<Range>
48   {
49     return std::ranges::size(range_);
50   }
51 
begin()52   auto begin() { return std::make_move_iterator(std::ranges::begin(range_)); }
end()53   auto end() { return std::make_move_iterator(std::ranges::end(range_)); }
54 
55  private:
56   // RAW_PTR_EXCLUSION: References a STACK_ALLOCATED class. It is only used
57   // inside for loops. Ideally, the container being iterated over should be the
58   // one held via a raw_ref/raw_ptrs.
59   RAW_PTR_EXCLUSION Range&& range_;
60 };
61 
62 // Internal adapter class for implementing base::Reversed.
63 // TODO(crbug.com/378623811): Parts of this (e.g. the `size()` helper) should be
64 // extracted to a base template that can be shared/reused. In addition, this
65 // should be constrained to Ts that satisfy the std::ranges::range concept.
66 template <typename Range>
67 class ReversedAdapter {
68  public:
ReversedAdapter(Range && range LIFETIME_BOUND)69   explicit ReversedAdapter(Range&& range LIFETIME_BOUND)
70       : range_(std::forward<Range>(range)) {}
71   ReversedAdapter(const ReversedAdapter&) = default;
72   ReversedAdapter& operator=(const ReversedAdapter&) = delete;
73 
begin()74   auto begin() { return std::rbegin(range_); }
begin()75   auto begin() const { return std::rbegin(range_); }
cbegin()76   auto cbegin() const { return std::crbegin(range_); }
77 
end()78   auto end() { return std::rend(range_); }
end()79   auto end() const { return std::rend(range_); }
cend()80   auto cend() const { return std::crend(range_); }
81 
size()82   auto size() const
83     requires std::ranges::sized_range<Range>
84   {
85     return std::ranges::size(range_);
86   }
87 
88  private:
89   // RAW_PTR_EXCLUSION: References a STACK_ALLOCATED class. It is only used
90   // inside for loops. Ideally, the container being iterated over should be the
91   // one held via a raw_ref/raw_ptrs.
92   RAW_PTR_EXCLUSION Range&& range_;
93 };
94 
95 }  // namespace base::internal
96 
97 #endif  // BASE_CONTAINERS_ADAPTERS_INTERNAL_H_
98