| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef BASE_CONTAINERS_ADAPTERS_INTERNAL_H_ |
| #define BASE_CONTAINERS_ADAPTERS_INTERNAL_H_ |
| |
| #include <stddef.h> |
| |
| #include <iterator> |
| #include <ranges> |
| #include <utility> |
| |
| #include "base/compiler_specific.h" |
| #include "base/memory/raw_ptr_exclusion.h" |
| |
| namespace base::internal { |
| template <typename Range> |
| class RangeOfRvaluesAdapter; |
| template <typename Range> |
| class ReversedAdapter; |
| } // namespace base::internal |
| |
| // This is technically correct, but presently always evaluates to false since |
| // `RangeAsRvalues()` bans non-borrowed ranges. |
| template <typename Range> |
| inline constexpr bool std::ranges::enable_borrowed_range< |
| base::internal::RangeOfRvaluesAdapter<Range>> = |
| std::ranges::borrowed_range<Range>; |
| |
| template <typename Range> |
| inline constexpr bool |
| std::ranges::enable_borrowed_range<base::internal::ReversedAdapter<Range>> = |
| std::ranges::borrowed_range<Range>; |
| |
| namespace base::internal { |
| |
| template <typename Range> |
| class RangeOfRvaluesAdapter { |
| public: |
| explicit RangeOfRvaluesAdapter(Range&& range LIFETIME_BOUND) |
| : range_(std::forward<Range>(range)) {} |
| RangeOfRvaluesAdapter(const RangeOfRvaluesAdapter&) = default; |
| RangeOfRvaluesAdapter& operator=(const RangeOfRvaluesAdapter&) = delete; |
| |
| auto size() const |
| requires std::ranges::sized_range<Range> |
| { |
| return std::ranges::size(range_); |
| } |
| |
| auto begin() { return std::make_move_iterator(std::ranges::begin(range_)); } |
| auto end() { return std::make_move_iterator(std::ranges::end(range_)); } |
| |
| private: |
| // RAW_PTR_EXCLUSION: References a STACK_ALLOCATED class. It is only used |
| // inside for loops. Ideally, the container being iterated over should be the |
| // one held via a raw_ref/raw_ptrs. |
| RAW_PTR_EXCLUSION Range&& range_; |
| }; |
| |
| // Internal adapter class for implementing base::Reversed. |
| // TODO(crbug.com/378623811): Parts of this (e.g. the `size()` helper) should be |
| // extracted to a base template that can be shared/reused. In addition, this |
| // should be constrained to Ts that satisfy the std::ranges::range concept. |
| template <typename Range> |
| class ReversedAdapter { |
| public: |
| explicit ReversedAdapter(Range&& range LIFETIME_BOUND) |
| : range_(std::forward<Range>(range)) {} |
| ReversedAdapter(const ReversedAdapter&) = default; |
| ReversedAdapter& operator=(const ReversedAdapter&) = delete; |
| |
| auto begin() { return std::rbegin(range_); } |
| auto begin() const { return std::rbegin(range_); } |
| auto cbegin() const { return std::crbegin(range_); } |
| |
| auto end() { return std::rend(range_); } |
| auto end() const { return std::rend(range_); } |
| auto cend() const { return std::crend(range_); } |
| |
| auto size() const |
| requires std::ranges::sized_range<Range> |
| { |
| return std::ranges::size(range_); |
| } |
| |
| private: |
| // RAW_PTR_EXCLUSION: References a STACK_ALLOCATED class. It is only used |
| // inside for loops. Ideally, the container being iterated over should be the |
| // one held via a raw_ref/raw_ptrs. |
| RAW_PTR_EXCLUSION Range&& range_; |
| }; |
| |
| } // namespace base::internal |
| |
| #endif // BASE_CONTAINERS_ADAPTERS_INTERNAL_H_ |