Files
2025-10-25 03:02:53 +03:00

13 KiB
Raw Permalink Blame History

[range.cache.latest]

25 Ranges library [ranges]

25.7 Range adaptors [range.adaptors]

25.7.34 Cache latest view [range.cache.latest]

25.7.34.1 Overview [range.cache.latest.overview]

1

#

cache_latest_view caches the last-accessed element of its underlying sequence so that the element does not have to be recomputed on repeated access.

[Note 1:

This is useful if computation of the element to produce is expensive.

— end note]

2

#

The name views::cache_latest denotes a range adaptor object ([range.adaptor.object]).

Let E be an expression.

The expression views::cache_latest(E) is expression-equivalent tocache_latest_view(E).

25.7.34.2 Class template cache_latest_view [range.cache.latest.view]

namespace std::ranges {template<input_range V>requires viewclass cache_latest_view : public view_interface<cache_latest_view> { V base_ = V(); // exposition onlyusing cache-t = conditional_t<is_reference_v<range_reference_t>, // exposition only add_pointer_t<range_reference_t>, range_reference_t>; non-propagating-cache<cache-t> cache_; // exposition only// [range.cache.latest.iterator], class cache_latest_view::iteratorclass iterator; // exposition only// [range.cache.latest.sentinel], class cache_latest_view::sentinelclass sentinel; // exposition onlypublic: cache_latest_view() requires default_initializable = default; constexpr explicit cache_latest_view(V base); constexpr V base() const & requires copy_constructible { return base_; }constexpr V base() && { return std::move(base_); }constexpr auto begin(); constexpr auto end(); constexpr auto size() requires sized_range; constexpr auto size() const requires sized_range; constexpr auto reserve_hint() requires approximately_sized_range; constexpr auto reserve_hint() const requires approximately_sized_range; }; template cache_latest_view(R&&) -> cache_latest_view<views::all_t>;}

🔗

constexpr explicit cache_latest_view(V base);

1

#

Effects: Initializes base_ with std::move(base).

🔗

constexpr auto begin();

2

#

Effects: Equivalent to: return iterator(*this);

🔗

constexpr auto end();

3

#

Effects: Equivalent to: return sentinel(*this);

🔗

constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<V>; constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<const V>;

4

#

Effects: Equivalent to: return ranges::size(base_);

🔗

constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3Approximately sized ranges[range.approximately.sized]")<V>; constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3Approximately sized ranges[range.approximately.sized]")<const V>;

5

#

Effects: Equivalent to: return ranges::reserve_hint(base_);

25.7.34.3 Class cache_latest_view::iterator [range.cache.latest.iterator]

🔗

namespace std::ranges {template<input_range V>requires viewclass cache_latest_view::iterator { cache_latest_view* parent_; // exposition only iterator_t current_; // exposition onlyconstexpr explicit iterator(cache_latest_view& parent); // exposition onlypublic:using difference_type = range_difference_t; using value_type = range_value_t; using iterator_concept = input_iterator_tag; iterator(iterator&&) = default; iterator& operator=(iterator&&) = default; constexpr iterator_t base() &&; constexpr const iterator_t& base() const & noexcept; constexpr range_reference_t& operator*() const; constexpr iterator& operator++(); constexpr void operator++(int); friend constexpr range_rvalue_reference_t iter_move(const iterator& i)noexcept(noexcept(ranges::iter_move(i.current_))); friend constexpr void iter_swap(const iterator& x, const iterator& y)noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))requires indirectly_swappable<iterator_t>; };}

🔗

constexpr explicit iterator(cache_latest_view& parent);

1

#

Effects: Initializes current_ withranges::begin(parent.base_) and parent_ with addressof(parent).

🔗

constexpr iterator_t<V> base() &&;

2

#

Returns: std::move(current_).

🔗

constexpr const iterator_t<V>& base() const & noexcept;

3

#

Returns: current_.

🔗

constexpr iterator& operator++();

4

#

Effects: Equivalent to:parent_->cache_.reset();++current_;return *this;

🔗

constexpr void operator++(int);

5

#

Effects: Equivalent to: ++*this.

🔗

constexpr range_reference_t<V>& operator*() const;

6

#

Effects: Equivalent to:if constexpr (is_reference_v<range_reference_t>) {if (!parent_->cache_) {parent_->cache_ = addressof(as-lvalue(**current_)); }return parent_->cache_;} else {if (!parent_->cache_) {parent_->cache_.emplace-deref(current_); }return **parent_->cache_;}

[Note 1:

Evaluations of operator* on the same iterator object can conflict ([intro.races]).

— end note]

🔗

friend constexpr range_rvalue_reference_t<V> iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_)));

7

#

Effects: Equivalent to: return ranges::iter_move(i.current_);

🔗

friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.current_, y.current_))) requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4Concept indirectly_­swappable[alg.req.ind.swap]")<iterator_t<V>>;

8

#

Effects: Equivalent toranges::iter_swap(x.current_, y.current_).

25.7.34.4 Class cache_latest_view::sentinel [range.cache.latest.sentinel]

🔗

namespace std::ranges {template<input_range V>requires viewclass cache_latest_view::sentinel { sentinel_t end_ = sentinel_t(); // exposition onlyconstexpr explicit sentinel(cache_latest_view& parent); // exposition onlypublic:sentinel() = default; constexpr sentinel_t base() const; friend constexpr bool operator==(const iterator& x, const sentinel& y); friend constexpr range_difference_t operator-(const iterator& x, const sentinel& y)requires sized_sentinel_for<sentinel_t, iterator_t>; friend constexpr range_difference_t operator-(const sentinel& x, const iterator& y)requires sized_sentinel_for<sentinel_t, iterator_t>; };}

🔗

constexpr explicit sentinel(cache_latest_view& parent);

1

#

Effects: Initializes end_ with ranges::end(parent.base_).

🔗

constexpr sentinel_t<V> base() const;

2

#

Returns: end_.

🔗

friend constexpr bool operator==(const iterator& x, const sentinel& y);

3

#

Returns: x.current_ == y.end_.

🔗

friend constexpr range_difference_t<V> operator-(const iterator& x, const sentinel& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<sentinel_t<V>, iterator_t<V>>;

4

#

Returns: x.current_ - y.end_.

🔗

friend constexpr range_difference_t<V> operator-(const sentinel& x, const iterator& y) requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<sentinel_t<V>, iterator_t<V>>;

5

#

Returns: x.end_ - y.current_.