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