namespace std::ranges {
template<input_range V>
requires view<V>
class cache_latest_view : public view_interface<cache_latest_view<V>> { …… }; // (1)
namespace views {
inline constexpr /*unspecified*/ cache_latest = /*unspecified*/; // (2)
}
}
概要
- (1): 元のRangeの最後にアクセスした要素 (間接参照結果) をキャッシュする
view - (2):
cache_latest_viewを生成するRangeアダプタオブジェクト
views::transformとviews::filterを組み合わせた場合、filterが条件判定のために要素を間接参照し、さらにfor文の本体で同じ要素を参照することにより、変換関数が2回呼び出される。cache_latestを間に挟むことで、間接参照の結果をキャッシュし、変換関数の重複呼び出しを回避できる。
v | std::views::transform(expensive) // 重い変換関数
| std::views::cache_latest // 変換結果をキャッシュ
| std::views::filter(pred)
キャッシュ戦略は、元のRangeの参照型が参照型である場合はポインタを、非参照型 (prvalue) である場合は値そのものを保持する。
Rangeコンセプト
| borrowed | sized | output | input | forward | bidirectional | random_access | contiguous | common | viewable | view |
|---|---|---|---|---|---|---|---|---|---|---|
| ※ | ○ | ○ | ○ |
- ※:
Vがsized_rangeのとき - イテレータと番兵の型が異なるため
common_rangeではない - 内部状態としてキャッシュを持つため
forward_range以上にはならない - キャッシュへのポインタを保持するため
borrowed_rangeではない
テンプレートパラメータ制約
input_range<V>view<V>
効果
- (2): 式
views::cache_latest(E)の効果はcache_latest_view(E)と等しい
メンバ関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
(constructor) |
コンストラクタ | C++26 |
base |
Vの参照を取得する |
C++26 |
begin |
先頭を指すイテレータを取得する | C++26 |
end |
番兵を取得する | C++26 |
size |
要素数を取得する | C++26 |
reserve_hint |
要素数の推定値を取得する | C++26 |
継承しているメンバ関数
| 名前 | 説明 | 対応バージョン |
|---|---|---|
empty |
Rangeが空かどうかを判定する | C++26 |
operator bool |
Rangeが空でないかどうかを判定する | C++26 |
front |
先頭要素への参照を取得する | C++26 |
メンバ型
| 名前 | 説明 | 対応バージョン |
|---|---|---|
iterator |
イテレータ型(説明専用) | C++26 |
sentinel |
番兵型(説明専用) | C++26 |
推論補助
| 名前 | 説明 | 対応バージョン |
|---|---|---|
(deduction_guide) |
クラステンプレートの推論補助 | C++26 |
備考
- このビュー(および
views::cache_latestアダプタ)は、フリースタンディング処理系でも使用できる。
例
基本的な使い方
#include <ranges>
#include <print>
#include <vector>
int main()
{
std::vector v = {1, 2, 3, 4, 5};
for (auto x : v | std::views::cache_latest) {
std::println("{}", x);
}
}
出力
1
2
3
4
5
変換関数の重複呼び出しを抑える
views::transformで重い変換を行い、views::filterで絞り込む場合、filterが条件判定で要素を間接参照し、その後の処理で再度間接参照されるため、変換関数が要素ごとに複数回呼び出される。間にcache_latestを挟むことで、変換関数の呼び出しを各要素1回に抑えられる。
#include <ranges>
#include <print>
#include <vector>
int main()
{
std::vector v = {1, 2, 3, 4, 5};
int call_count = 0;
auto square = [&](int x) { ++call_count; return x * x; };
for (auto x : v | std::views::transform(square)
| std::views::cache_latest
| std::views::filter([](int n) { return n > 5; })) {
std::println("{}", x);
}
std::println("call_count: {}", call_count);
}
出力
9
16
25
call_count: 5
バージョン
言語
- C++26
処理系
- Clang: 21 ✅
- GCC: 15.1 ✅
- Visual C++: 2026 Update 2 ❌
関連項目
参照
- P3138R5
views::cache_latest - LWG Issue 4189.
cache_latest_viewshould be freestanding- C++26で、このビューがフリースタンディング処理系に対応した
- LWG Issue 4235.
cache_latest_viewandto_input_viewmissreserve_hint- C++26で、
approximately_sized_rangeのときに要素数の推定値を返すreserve_hintメンバ関数が追加された
- C++26で、