<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-11-18" />
  <title>views::cache_latest</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span. { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit; 
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }

span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none; 
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }

code.sourceCode > span { display: inline; }
</style>
  <style type="text/css">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
.marginalized:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #e6ffed;
--diff-strongins: #acf2bd;
--diff-del: #ffdddd;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre, div.add blockquote { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
blockquote { background-color: #f6f8fa; }
@media (prefers-color-scheme: dark) {
:root {
--diff-ins: #225522;
--diff-strongins: #225522;
--diff-del: #662222;
--diff-strongdel: #662222;
}
body {
background-color: #171717;
color: #b0b0b0;
}
table tr {
background-color: #171717;
}
table tr:nth-child(2n) {
background-color: #252525;
}
#title-block-header > table tr:nth-child(2n) {
background-color: #171717;
}
tr.header {
border-bottom: 3px solid #b0b0b0;
border-bottom-style: double;
}
tr.even, tr.odd {
border-bottom: 1px solid #b0b0b0;
}
table th {
border-bottom: 1px solid #b0b0b0;
}
table tbody tr:first-child td {
border-top: 1px solid #b0b0b0;
}
blockquote { background-color: rgba(255, 255, 255, .03); }
a { color: #549df2; }
div.sourceCode
{ background-color: rgba(255, 255, 255, .03); }
table { border-color: #b0b0b0; }
td.border { border-color: #b0b0b0; }
td.border { border-left-color: #b0b0b0; }
tr.rowsep, td.cline { border-top-color: #b0b0b0; }
tr.capsep { border-top-color: #b0b0b0; }
th { border-bottom-color: #b0b0b0; }
code span.kw { color: #12cabe; }
code span.cf { color: #12cabe; }
code span.op { color: #cf1915; }
code span.pp { color: #b27c58; }
code span.co { color: #35ba00; }
code.diff span.va {
color: #b0b0b0;
}
code.diff span.vd {
color: #b0b0b0;
}
code.diff span.st {
color: #b0b0b0;
}
div.add {
color: #d0fddd !important
}
div.rm {
color: #8f3131 !important
}
div.rm pre, div.add pre { background-color: rgba(255, 255, 255, .03); }
}
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
  
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center"><code class="sourceCode cpp">views<span class="op">::</span>cache_latest</code></h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3138R5</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-11-18</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      LWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Tim Song<br>&lt;<a href="mailto:t.canens.cpp@gmail.com" class="email">t.canens.cpp@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>

</header>
<div style="clear:both">
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>This paper proposes the <code class="sourceCode cpp">views<span class="op">::</span>cache_latest</code> adaptor that caches the result of the last dereference of the underlying iterator.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="revision-history"><span class="header-section-number">2</span> Revision history<a href="#revision-history" class="self-link"></a></h1>
<ul>
<li>R5: Incorporated LWG review feedback.</li>
<li>R4: Added <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">-</span></code> for <code class="sourceCode cpp">sized_sentinel_for</code> cases.</li>
<li>R3: Rename to <code class="sourceCode cpp">cache_latest</code> per SG9 feedback.</li>
<li>R2: Removed the quasi-drive-by fix to <span>16.4.6.10 <a href="https://eel.is/c++draft/res.on.data.races">[res.on.data.races]</a></span> per St. Louis SG1 feedback; it will be addressed as an LWG issue. Added feature-test macro.</li>
<li>R1: Limited the <span>16.4.6.10 <a href="https://eel.is/c++draft/res.on.data.races">[res.on.data.races]</a></span> carve-out to this adaptor per SG1 feedback.</li>
</ul>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="motivation"><span class="header-section-number">3</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>The motivation for this view is given in <span class="citation" data-cites="P2760R1">[<a href="#ref-P2760R1" role="doc-biblioref">P2760R1</a>]</span> (under the name <code class="sourceCode cpp">cache_last</code>) and quoted below for convenience:</p>
<blockquote>
<p>One of the adaptors that we considered for C++23 but ended up not pursuing was what range-v3 calls <code class="sourceCode cpp">cache1</code> and what we’d instead like to call something like <code class="sourceCode cpp">cache_last</code>. This is an adaptor which, as the name suggests, caches the last element. The reason for this is efficiency - specifically avoiding extra work that has to be done by iterator dereferencing.</p>
<p>The canonical example of this is <code class="sourceCode cpp">transform<span class="op">(</span>f<span class="op">)</span> <span class="op">|</span> filter<span class="op">(</span>g<span class="op">)</span></code>, where if you then iterate over the subsequent range, <code class="sourceCode cpp">f</code> will be invoked twice for every element that satisfies <code class="sourceCode cpp">g</code>:</p>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="dt">int</span> main<span class="op">()</span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3"></a>    std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> v <span class="op">=</span> <span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span><span class="op">}</span>;</span>
<span id="cb1-4"><a href="#cb1-4"></a></span>
<span id="cb1-5"><a href="#cb1-5"></a>    <span class="kw">auto</span> even_squares <span class="op">=</span> v</span>
<span id="cb1-6"><a href="#cb1-6"></a>        <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">([](</span><span class="dt">int</span> i<span class="op">){</span></span>
<span id="cb1-7"><a href="#cb1-7"></a>                std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;transform: {}</span><span class="sc">\n</span><span class="st">&quot;</span>, i<span class="op">)</span>;</span>
<span id="cb1-8"><a href="#cb1-8"></a>                <span class="cf">return</span> i <span class="op">*</span> i;</span>
<span id="cb1-9"><a href="#cb1-9"></a>            <span class="op">})</span></span>
<span id="cb1-10"><a href="#cb1-10"></a>        <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>filter<span class="op">([](</span><span class="dt">int</span> i<span class="op">){</span></span>
<span id="cb1-11"><a href="#cb1-11"></a>                std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;filter: {}</span><span class="sc">\n</span><span class="st">&quot;</span>, i<span class="op">)</span>;</span>
<span id="cb1-12"><a href="#cb1-12"></a>                <span class="cf">return</span> i <span class="op">%</span> <span class="dv">2</span> <span class="op">==</span> <span class="dv">0</span>;</span>
<span id="cb1-13"><a href="#cb1-13"></a>            <span class="op">})</span>;</span>
<span id="cb1-14"><a href="#cb1-14"></a></span>
<span id="cb1-15"><a href="#cb1-15"></a>    <span class="cf">for</span> <span class="op">(</span><span class="dt">int</span> i <span class="op">:</span> even_squares<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-16"><a href="#cb1-16"></a>        std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;Got: {}</span><span class="sc">\n</span><span class="st">&quot;</span>, i<span class="op">)</span>;</span>
<span id="cb1-17"><a href="#cb1-17"></a>    <span class="op">}</span></span>
<span id="cb1-18"><a href="#cb1-18"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>prints the following (note that there are 7 invocations of <code class="sourceCode cpp">transform</code>):</p>
<blockquote>
<div class="sourceCode" id="cb2"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb2-1"><a href="#cb2-1"></a>transform: 1</span>
<span id="cb2-2"><a href="#cb2-2"></a>filter: 1</span>
<span id="cb2-3"><a href="#cb2-3"></a>transform: 2</span>
<span id="cb2-4"><a href="#cb2-4"></a>filter: 4</span>
<span id="cb2-5"><a href="#cb2-5"></a>transform: 2</span>
<span id="cb2-6"><a href="#cb2-6"></a>Got: 4</span>
<span id="cb2-7"><a href="#cb2-7"></a>transform: 3</span>
<span id="cb2-8"><a href="#cb2-8"></a>filter: 9</span>
<span id="cb2-9"><a href="#cb2-9"></a>transform: 4</span>
<span id="cb2-10"><a href="#cb2-10"></a>filter: 16</span>
<span id="cb2-11"><a href="#cb2-11"></a>transform: 4</span>
<span id="cb2-12"><a href="#cb2-12"></a>Got: 16</span>
<span id="cb2-13"><a href="#cb2-13"></a>transform: 5</span>
<span id="cb2-14"><a href="#cb2-14"></a>filter: 25</span></code></pre></div>
</blockquote>
<p>The solution here is to add a layer of caching:</p>
<blockquote>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="kw">auto</span> even_squares <span class="op">=</span> v</span>
<span id="cb3-2"><a href="#cb3-2"></a>    <span class="op">|</span> views<span class="op">::</span>transform<span class="op">(</span>square<span class="op">)</span></span>
<span id="cb3-3"><a href="#cb3-3"></a>    <span class="op">|</span> views<span class="op">::</span>cache_last</span>
<span id="cb3-4"><a href="#cb3-4"></a>    <span class="op">|</span> views<span class="op">::</span>filter<span class="op">(</span>is_even<span class="op">)</span>;</span></code></pre></div>
</blockquote>
<p>Which will ensure that <code class="sourceCode cpp">square</code> will only be called once per element.</p>
</blockquote>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="design"><span class="header-section-number">4</span> Design<a href="#design" class="self-link"></a></h1>
<h2 data-number="4.1" id="caching-in-operator"><span class="header-section-number">4.1</span> Caching in <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">*</span></code><a href="#caching-in-operator" class="self-link"></a></h2>
<p>This is the only reasonable place for this caching to happen. Caching in <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">++</span></code> would require unnecessary overhead on every traversal if the user does not need to dereference every iterator (e.g., a striding view).</p>
<h2 data-number="4.2" id="relaxing-res.on.data.races"><span class="header-section-number">4.2</span> Relaxing [res.on.data.races]<a href="#relaxing-res.on.data.races" class="self-link"></a></h2>
<p>Because <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">*</span></code> is required to be a <code class="sourceCode cpp"><span class="kw">const</span></code> member function (the cost of relaxing that requirement would be prohibitive as it affects every iterator and range adaptor), yet we want to have it perform a potentially-modifying operation, our options are basically:</p>
<ul>
<li>Make this an exception to <span>16.4.6.10 <a href="https://eel.is/c++draft/res.on.data.races">[res.on.data.races]</a></span> p3</li>
<li>Require synchronization.</li>
</ul>
<p>This paper proposes the former. Input-only iterators, in general, are poor candidates for sharing across threads because, even when copyable (and they are not required to be in C++20), they are subject to “spooky action at a distance” where incrementing one iterator invalidates all copies thereof. This is why parallel algorithms require at least forward iterators. Sharing references to the same input iterator across threads seems like a fairly contrived scenario.</p>
<p>Moreover, <code class="sourceCode cpp">std<span class="op">::</span>istreambuf_iterator</code> already doesn’t meet this requirement in <a href="https://lists.isocpp.org/lib/2023/03/25724.php">every major standard library implementation</a> yet it does not seem to have appeared on any standard library maintainer’s radar in the decade since the publication of C++11. This further suggests that this guarantee is not relied upon in practice for input-only iterators.</p>
<p>It is true that we could require synchronization on <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span></code>. This probably isn’t terrible expensive in this context (we only need to protect against <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">*</span></code> calls racing with each other, not them racing with <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">++</span></code>), but adding synchronization to an adaptor whose primary purpose is to improve performance seems particularly dissatisfying when that synchronization will almost never be actually necessary.</p>
<p>During the Tokyo SG1 meeting, the room favored a limited carve-out to <span>16.4.6.10 <a href="https://eel.is/c++draft/res.on.data.races">[res.on.data.races]</a></span> for this adaptor only. As it turns out, p1 of that subclause already has “unless otherwise specified”, so we don’t need to make any additional modification there. However, the wording is unclear how any of the requirements apply to templated functions in the standard library; this will be addressed separately as an issue.</p>
<h2 data-number="4.3" id="whats-the-reference-type"><span class="header-section-number">4.3</span> What’s the reference type?<a href="#whats-the-reference-type" class="self-link"></a></h2>
<p>range-v3 uses <code class="sourceCode cpp">range_value_t<span class="op">&lt;</span>V<span class="op">&gt;&amp;&amp;</span></code>, but this somewhat defeats the purpose of caching if you can so easily invalidate it. Moreover, there doesn’t seem to be a reason to force an independent copy of the <code class="sourceCode cpp">value_type</code>. So long as the underlying iterator is not modified, the reference obtained from <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">*</span></code> should remain valid.</p>
<p>This paper therefore proposes <code class="sourceCode cpp">range_reference_t<span class="op">&lt;</span>V<span class="op">&gt;&amp;</span></code>. Note that even if the reference type is a real reference, it can be an <em>expensive-to-compute</em> reference, so caching could still make sense.</p>
<h2 data-number="4.4" id="properties"><span class="header-section-number">4.4</span> Properties<a href="#properties" class="self-link"></a></h2>
<p><code class="sourceCode cpp">cache_latest</code> is never borrowed, input-only, never common, and not const-iterable.</p>
<h2 data-number="4.5" id="iter_move-and-iter_swap"><span class="header-section-number">4.5</span> <code class="sourceCode cpp">iter_move</code> and <code class="sourceCode cpp">iter_swap</code><a href="#iter_move-and-iter_swap" class="self-link"></a></h2>
<p><code class="sourceCode cpp">indirectly_readable</code> and <code class="sourceCode cpp">indirectly_swappable</code> requires <code class="sourceCode cpp">iter_move</code> and <code class="sourceCode cpp">iter_swap</code> to respectively not modify <code class="sourceCode cpp">i</code> (in the <span>18.2 <a href="https://eel.is/c++draft/concepts.equality">[concepts.equality]</a></span> sense). Moreover, <code class="sourceCode cpp">indirectly_readable</code> requires <code class="sourceCode cpp"><span class="op">*</span>i</code> to be equality-preserving. So the cache should not be invalidated by either operation. (The underlying element might be modified, but the reference itself, obtained from dereferencing the iterator, cannot.)</p>
<h2 data-number="4.6" id="naming"><span class="header-section-number">4.6</span> Naming<a href="#naming" class="self-link"></a></h2>
<p>range-v3 calls this <code class="sourceCode cpp">cache1</code>, which is not a particularly informative name (what does the “1” stand for)? The ranges plan papers oscillated between <code class="sourceCode cpp">cache_last</code> and <code class="sourceCode cpp">cache_latest</code> for no clear reason. SG9’s naming poll was a tie between <code class="sourceCode cpp">cache<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;</span></code> and <code class="sourceCode cpp">cache_latest</code>. The author does not consider the first viable (it is unclear what <code class="sourceCode cpp">cache<span class="op">&lt;</span><span class="dv">2</span><span class="op">&gt;</span></code> would mean when the caching implies an input range which can only ever represent one position). However, <code class="sourceCode cpp">last</code> might be confused for the last element in the range (i.e., <code class="sourceCode cpp">back<span class="op">()</span></code>) or the past-the-end position(as in <code class="sourceCode cpp"><span class="op">[</span>first, last<span class="op">)</span></code>) while <code class="sourceCode cpp">latest</code> does not have this issue.</p>
<p>R3 of this paper accordingly renamed the proposed view to <code class="sourceCode cpp">cache_latest</code>.</p>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="wording"><span class="header-section-number">5</span> Wording<a href="#wording" class="self-link"></a></h1>
<p>This wording is relative to <span class="citation" data-cites="N4971">[<a href="#ref-N4971" role="doc-biblioref">N4971</a>]</span>.</p>
<h2 data-number="5.1" id="addition-to-ranges"><span class="header-section-number">5.1</span> Addition to <code class="sourceCode cpp"><span class="op">&lt;</span>ranges<span class="op">&gt;</span></code><a href="#addition-to-ranges" class="self-link"></a></h2>
<p>Add the following to <span>25.2 <a href="https://eel.is/c++draft/ranges.syn">[ranges.syn]</a></span>, header <code class="sourceCode cpp"><span class="op">&lt;</span>ranges<span class="op">&gt;</span></code> synopsis:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="co">// [...]</span></span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3"></a>  <span class="co">// [...]</span></span>
<span id="cb4-4"><a href="#cb4-4"></a></span>
<span id="cb4-5"><a href="#cb4-5"></a>  <span class="co">// [range.cache.latest], cache latest view</span></span>
<span id="cb4-6"><a href="#cb4-6"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range V<span class="op">&gt;</span></span>
<span id="cb4-7"><a href="#cb4-7"></a>    <span class="kw">requires</span> view<span class="op">&lt;</span>V<span class="op">&gt;</span></span>
<span id="cb4-8"><a href="#cb4-8"></a>  <span class="kw">class</span> cache_latest_view;</span>
<span id="cb4-9"><a href="#cb4-9"></a></span>
<span id="cb4-10"><a href="#cb4-10"></a>  <span class="kw">namespace</span> views <span class="op">{</span></span>
<span id="cb4-11"><a href="#cb4-11"></a>    <span class="kw">inline</span> <span class="kw">constexpr</span> <em>unspecified</em> cache_latest <span class="op">=</span> <em>unspecified</em>;</span>
<span id="cb4-12"><a href="#cb4-12"></a>  <span class="op">}</span></span>
<span id="cb4-13"><a href="#cb4-13"></a></span>
<span id="cb4-14"><a href="#cb4-14"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="5.2" id="cache_latest"><span class="header-section-number">5.2</span> <code class="sourceCode cpp">cache_latest</code><a href="#cache_latest" class="self-link"></a></h2>
<p>Add the following subclause to <span>25.7 <a href="https://eel.is/c++draft/range.adaptors">[range.adaptors]</a></span>:</p>
<h3 class="unnumbered" data-number id="cache-latest-view-range.cache.latest">26.7.? Cache latest view [range.cache.latest]<a href="#cache-latest-view-range.cache.latest" class="self-link"></a></h3>
<h4 class="unnumbered" data-number id="overview-range.cache.latest.overview">26.7.?.1 Overview [range.cache.latest.overview]<a href="#overview-range.cache.latest.overview" class="self-link"></a></h4>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">1</a></span> <code class="sourceCode cpp">cache_latest_view</code> caches the last-accessed element of its underlying sequence so that the element does not have to be recomputed on repeated access. <span class="note"><span>[ <em>Note 1:</em> </span>This is useful if computation of the element to produce is expensive.<span> — <em>end note</em> ]</span></span></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">2</a></span> The name <code class="sourceCode cpp">views<span class="op">::</span>cache_latest</code> denotes a range adaptor object (<span>25.7.2 <a href="https://eel.is/c++draft/range.adaptor.object">[range.adaptor.object]</a></span>). Let <code class="sourceCode cpp">E</code> be an expression. The expression <code class="sourceCode cpp">views​<span class="op">::</span>cache_latest<span class="op">(</span>E<span class="op">)</span></code> is expression-equivalent to <code class="sourceCode cpp">cache_latest_view<span class="op">(</span>E<span class="op">)</span></code>. <span class="draftnote" style="color: #01796F">[ Drafting note: Intentional CTAD to avoid double wrapping if <code class="sourceCode cpp">E</code> is already a <code class="sourceCode cpp">cache_latest_view</code>. ]</span></p>
<h4 class="unnumbered" data-number id="class-template-cache_latest_view-range.cache.latest.view">26.7.?.2 Class template <code class="sourceCode cpp">cache_latest_view</code> [range.cache.latest.view]<a href="#class-template-cache_latest_view-range.cache.latest.view" class="self-link"></a></h4>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="kw">template</span><span class="op">&lt;</span>input_range V<span class="op">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2"></a>  <span class="kw">requires</span> view<span class="op">&lt;</span>V<span class="op">&gt;</span></span>
<span id="cb5-3"><a href="#cb5-3"></a><span class="kw">class</span> cache_latest_view <span class="op">:</span> <span class="kw">public</span> view_interface<span class="op">&lt;</span>cache_latest_view<span class="op">&lt;</span>V<span class="op">&gt;&gt;{</span></span>
<span id="cb5-4"><a href="#cb5-4"></a>  V <em>base_</em> <span class="op">=</span> V<span class="op">()</span>;                                                       <span class="co">// exposition only</span></span>
<span id="cb5-5"><a href="#cb5-5"></a>  <span class="kw">using</span> <em>cache_t</em> <span class="op">=</span> conditional_t<span class="op">&lt;</span>is_reference_v<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>V<span class="op">&gt;&gt;</span>,  <span class="co">// exposition only</span></span>
<span id="cb5-6"><a href="#cb5-6"></a>                                add_pointer_t<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>V<span class="op">&gt;&gt;</span>,</span>
<span id="cb5-7"><a href="#cb5-7"></a>                                range_reference_t<span class="op">&lt;</span>V<span class="op">&gt;&gt;</span>;</span>
<span id="cb5-8"><a href="#cb5-8"></a></span>
<span id="cb5-9"><a href="#cb5-9"></a>  <em>non-propagating-cache</em><span class="op">&lt;</span><em>cache_t</em><span class="op">&gt;</span> <em>cache_</em>;                               <span class="co">// exposition only</span></span>
<span id="cb5-10"><a href="#cb5-10"></a></span>
<span id="cb5-11"><a href="#cb5-11"></a>  <span class="kw">class</span> <em>iterator</em>;                                                      <span class="co">// exposition only</span></span>
<span id="cb5-12"><a href="#cb5-12"></a>  <span class="kw">class</span> <em>sentinel</em>;                                                      <span class="co">// exposition only</span></span>
<span id="cb5-13"><a href="#cb5-13"></a></span>
<span id="cb5-14"><a href="#cb5-14"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb5-15"><a href="#cb5-15"></a>  cache_latest_view<span class="op">()</span> <span class="kw">requires</span> default_initializable<span class="op">&lt;</span>V<span class="op">&gt;</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb5-16"><a href="#cb5-16"></a>  <span class="kw">constexpr</span> <span class="kw">explicit</span> cache_latest_view<span class="op">(</span>V base<span class="op">)</span>;</span>
<span id="cb5-17"><a href="#cb5-17"></a></span>
<span id="cb5-18"><a href="#cb5-18"></a>  <span class="kw">constexpr</span> V base<span class="op">()</span> <span class="kw">const</span> <span class="op">&amp;</span> <span class="kw">requires</span> copy_constructible<span class="op">&lt;</span>V<span class="op">&gt;</span> <span class="op">{</span> <span class="cf">return</span> <em>base_</em>; <span class="op">}</span></span>
<span id="cb5-19"><a href="#cb5-19"></a>  <span class="kw">constexpr</span> V base<span class="op">()</span> <span class="op">&amp;&amp;</span> <span class="op">{</span> <span class="cf">return</span> std<span class="op">::</span>move<span class="op">(</span><em>base_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb5-20"><a href="#cb5-20"></a></span>
<span id="cb5-21"><a href="#cb5-21"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> begin<span class="op">()</span>;</span>
<span id="cb5-22"><a href="#cb5-22"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> end<span class="op">()</span>;</span>
<span id="cb5-23"><a href="#cb5-23"></a></span>
<span id="cb5-24"><a href="#cb5-24"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">requires</span> sized_range<span class="op">&lt;</span>V<span class="op">&gt;</span>;</span>
<span id="cb5-25"><a href="#cb5-25"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span> sized_range<span class="op">&lt;</span><span class="kw">const</span> V<span class="op">&gt;</span>;</span>
<span id="cb5-26"><a href="#cb5-26"></a><span class="op">}</span>;</span>
<span id="cb5-27"><a href="#cb5-27"></a></span>
<span id="cb5-28"><a href="#cb5-28"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> R<span class="op">&gt;</span></span>
<span id="cb5-29"><a href="#cb5-29"></a>  cache_latest_view<span class="op">(</span>R<span class="op">&amp;&amp;)</span> <span class="op">-&gt;</span> cache_latest_view<span class="op">&lt;</span>views<span class="op">::</span>all_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;</span>;</span></code></pre></div>
<div>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1"></a><span class="kw">constexpr</span> <span class="kw">explicit</span> cache_latest_view<span class="op">(</span>V base<span class="op">)</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">1</a></span> <em>Effects</em>: Initializes <code class="sourceCode cpp"><em>base_</em></code> with <code class="sourceCode cpp">std<span class="op">::</span>move<span class="op">(</span>base<span class="op">)</span></code>.</p>
</blockquote>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> begin<span class="op">()</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">2</a></span> <em>Effects</em>: Equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1"></a><span class="cf">return</span> <em>iterator</em><span class="op">(*</span><span class="kw">this</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</blockquote>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> end<span class="op">()</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_5" id="pnum_5">3</a></span> <em>Effects</em>: Equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1"></a><span class="cf">return</span> <em>sentinel</em><span class="op">(*</span><span class="kw">this</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</blockquote>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">requires</span> sized_range<span class="op">&lt;</span>V<span class="op">&gt;</span>;</span>
<span id="cb11-2"><a href="#cb11-2"></a><span class="kw">constexpr</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span> sized_range<span class="op">&lt;</span><span class="kw">const</span> V<span class="op">&gt;</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_6" id="pnum_6">4</a></span> <em>Effects</em>: Equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1"></a><span class="cf">return</span> ranges<span class="op">::</span>size<span class="op">(</span><em>base_</em><span class="op">)</span>;</span></code></pre></div>
</blockquote>
</blockquote>
</div>
<h4 class="unnumbered" data-number id="class-cache_latest_viewiterator-range.cache.latest.iterator">26.7.?.3 Class <code class="sourceCode cpp">cache_latest_view<span class="op">::</span><em>iterator</em></code> [range.cache.latest.iterator]<a href="#class-cache_latest_viewiterator-range.cache.latest.iterator" class="self-link"></a></h4>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb13-2"><a href="#cb13-2"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range V<span class="op">&gt;</span></span>
<span id="cb13-3"><a href="#cb13-3"></a>    <span class="kw">requires</span> view<span class="op">&lt;</span>V<span class="op">&gt;</span></span>
<span id="cb13-4"><a href="#cb13-4"></a>  <span class="kw">class</span> cache_latest_view<span class="op">&lt;</span>V<span class="op">&gt;::</span><em>iterator</em> <span class="op">{</span></span>
<span id="cb13-5"><a href="#cb13-5"></a>    cache_latest_view<span class="op">*</span> <em>parent_</em>;                                 <span class="co">// exposition only</span></span>
<span id="cb13-6"><a href="#cb13-6"></a>    iterator_t<span class="op">&lt;</span>V<span class="op">&gt;</span> <em>current_</em>;                                     <span class="co">// exposition only</span></span>
<span id="cb13-7"><a href="#cb13-7"></a></span>
<span id="cb13-8"><a href="#cb13-8"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> <em>iterator</em><span class="op">(</span>cache_latest_view<span class="op">&amp;</span> parent<span class="op">)</span>;     <span class="co">// exposition only</span></span>
<span id="cb13-9"><a href="#cb13-9"></a></span>
<span id="cb13-10"><a href="#cb13-10"></a>  <span class="kw">public</span><span class="op">:</span></span>
<span id="cb13-11"><a href="#cb13-11"></a>    <span class="kw">using</span> difference_type <span class="op">=</span> range_difference_t<span class="op">&lt;</span>V<span class="op">&gt;</span>;</span>
<span id="cb13-12"><a href="#cb13-12"></a>    <span class="kw">using</span> value_type <span class="op">=</span> range_value_t<span class="op">&lt;</span>V<span class="op">&gt;</span>;</span>
<span id="cb13-13"><a href="#cb13-13"></a>    <span class="kw">using</span> iterator_concept <span class="op">=</span> input_iterator_tag;</span>
<span id="cb13-14"><a href="#cb13-14"></a></span>
<span id="cb13-15"><a href="#cb13-15"></a>    <em>iterator</em><span class="op">(</span><em>iterator</em><span class="op">&amp;&amp;)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb13-16"><a href="#cb13-16"></a>    <em>iterator</em><span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><em>iterator</em><span class="op">&amp;&amp;)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb13-17"><a href="#cb13-17"></a></span>
<span id="cb13-18"><a href="#cb13-18"></a>    <span class="kw">constexpr</span> iterator_t<span class="op">&lt;</span>V<span class="op">&gt;</span> base<span class="op">()</span> <span class="op">&amp;&amp;</span>;</span>
<span id="cb13-19"><a href="#cb13-19"></a>    <span class="kw">constexpr</span> <span class="kw">const</span> iterator_t<span class="op">&lt;</span>V<span class="op">&gt;&amp;</span> base<span class="op">()</span> <span class="kw">const</span> <span class="op">&amp;</span> <span class="kw">noexcept</span>;</span>
<span id="cb13-20"><a href="#cb13-20"></a></span>
<span id="cb13-21"><a href="#cb13-21"></a>    <span class="kw">constexpr</span> range_reference_t<span class="op">&lt;</span>V<span class="op">&gt;&amp;</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span>;</span>
<span id="cb13-22"><a href="#cb13-22"></a></span>
<span id="cb13-23"><a href="#cb13-23"></a>    <span class="kw">constexpr</span> <em>iterator</em><span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span>;</span>
<span id="cb13-24"><a href="#cb13-24"></a>    <span class="kw">constexpr</span> <span class="dt">void</span> <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb13-25"><a href="#cb13-25"></a></span>
<span id="cb13-26"><a href="#cb13-26"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> range_rvalue_reference_t<span class="op">&lt;</span>V<span class="op">&gt;</span> iter_move<span class="op">(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> i<span class="op">)</span></span>
<span id="cb13-27"><a href="#cb13-27"></a>      <span class="kw">noexcept</span><span class="op">(</span><span class="kw">noexcept</span><span class="op">(</span>ranges<span class="op">::</span>iter_move<span class="op">(</span>i<span class="op">.</span><em>current_</em><span class="op">)))</span>;</span>
<span id="cb13-28"><a href="#cb13-28"></a></span>
<span id="cb13-29"><a href="#cb13-29"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">void</span> iter_swap<span class="op">(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> x, <span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> y<span class="op">)</span></span>
<span id="cb13-30"><a href="#cb13-30"></a>      <span class="kw">noexcept</span><span class="op">(</span><span class="kw">noexcept</span><span class="op">(</span>ranges<span class="op">::</span>iter_swap<span class="op">(</span>x<span class="op">.</span><em>current_</em>, y<span class="op">.</span><em>current_</em><span class="op">)))</span></span>
<span id="cb13-31"><a href="#cb13-31"></a>      <span class="kw">requires</span> indirectly_swappable<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span>V<span class="op">&gt;&gt;</span>;</span>
<span id="cb13-32"><a href="#cb13-32"></a>  <span class="op">}</span>;</span>
<span id="cb13-33"><a href="#cb13-33"></a><span class="op">}</span></span></code></pre></div>
<div>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1"></a><span class="kw">constexpr</span> <span class="kw">explicit</span> <em>iterator</em><span class="op">(</span>cache_latest_view<span class="op">&amp;</span> parent<span class="op">)</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_7" id="pnum_7">1</a></span> <em>Effects</em>: Initializes <code class="sourceCode cpp"><em>current_</em></code> with <code class="sourceCode cpp">ranges<span class="op">::</span>begin<span class="op">(</span>parent<span class="op">.</span><em>base_</em><span class="op">)</span></code> and <code class="sourceCode cpp"><em>parent_</em></code> with <code class="sourceCode cpp">addressof<span class="op">(</span>parent<span class="op">)</span></code>.</p>
</blockquote>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1"></a><span class="kw">constexpr</span> iterator_t<span class="op">&lt;</span>V<span class="op">&gt;</span> base<span class="op">()</span> <span class="op">&amp;&amp;</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_8" id="pnum_8">2</a></span> <em>Returns</em>: <code class="sourceCode cpp">std<span class="op">::</span>move<span class="op">(</span><em>current_</em><span class="op">)</span></code>.</p>
</blockquote>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1"></a><span class="kw">constexpr</span> <span class="kw">const</span> iterator_t<span class="op">&lt;</span>V<span class="op">&gt;&amp;</span> base<span class="op">()</span> <span class="kw">const</span> <span class="op">&amp;</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_9" id="pnum_9">3</a></span> <em>Returns</em>: <code class="sourceCode cpp"><em>current_</em></code>.</p>
</blockquote>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1"></a><span class="kw">constexpr</span> <em>iterator</em><span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_10" id="pnum_10">4</a></span> <em>Effects:</em> Equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1"></a>   <em>parent_</em><span class="op">-&gt;</span><em>cache_</em><span class="op">.</span>reset<span class="op">()</span>;</span>
<span id="cb18-2"><a href="#cb18-2"></a>   <span class="op">++</span><em>current_</em>;</span>
<span id="cb18-3"><a href="#cb18-3"></a>   <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span></code></pre></div>
</blockquote>
</blockquote>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1"></a><span class="kw">constexpr</span> <span class="dt">void</span> <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_11" id="pnum_11">5</a></span> <em>Effects</em>: Equivalent to: <code class="sourceCode cpp"><span class="op">++*</span><span class="kw">this</span></code>.</p>
</blockquote>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1"></a><span class="kw">constexpr</span> range_reference_t<span class="op">&lt;</span>V<span class="op">&gt;&amp;</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_12" id="pnum_12">6</a></span> <em>Effects</em>: Equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1"></a>  <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>is_reference_v<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>V<span class="op">&gt;&gt;)</span> <span class="op">{</span></span>
<span id="cb21-2"><a href="#cb21-2"></a>    <span class="cf">if</span> <span class="op">(!</span><em>parent_</em><span class="op">-&gt;</span><em>cache_</em><span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-3"><a href="#cb21-3"></a>      <em>parent_</em><span class="op">-&gt;</span><em>cache_</em> <span class="op">=</span> addressof<span class="op">(</span><em>as-lvalue</em><span class="op">(*</span><em>current_</em><span class="op">))</span>;</span>
<span id="cb21-4"><a href="#cb21-4"></a>    <span class="op">}</span></span>
<span id="cb21-5"><a href="#cb21-5"></a>    <span class="cf">return</span> <span class="op">**</span><em>parent_</em><span class="op">-&gt;</span><em>cache_</em>;</span>
<span id="cb21-6"><a href="#cb21-6"></a>  <span class="op">}</span></span>
<span id="cb21-7"><a href="#cb21-7"></a>  <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb21-8"><a href="#cb21-8"></a>    <span class="cf">if</span> <span class="op">(!</span><em>parent_</em><span class="op">-&gt;</span><em>cache_</em><span class="op">)</span> <span class="op">{</span></span>
<span id="cb21-9"><a href="#cb21-9"></a>      <em>parent_</em><span class="op">-&gt;</span><em>cache_</em><span class="op">.</span><em>emplace-deref</em><span class="op">(</span><em>current_</em><span class="op">)</span>;</span>
<span id="cb21-10"><a href="#cb21-10"></a>    <span class="op">}</span></span>
<span id="cb21-11"><a href="#cb21-11"></a>    <span class="cf">return</span> <span class="op">*</span><em>parent_</em><span class="op">-&gt;</span><em>cache_</em>;</span>
<span id="cb21-12"><a href="#cb21-12"></a>  <span class="op">}</span></span></code></pre></div>
</blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_13" id="pnum_13">7</a></span> <span class="note"><span>[ <em>Note 1:</em> </span>Evaluations of <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">*</span></code> on the same iterator object may conflict (<span>6.9.2.2 <a href="https://eel.is/c++draft/intro.races">[intro.races]</a></span>).<span> — <em>end note</em> ]</span></span></p>
</blockquote>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> range_rvalue_reference_t<span class="op">&lt;</span>V<span class="op">&gt;</span> iter_move<span class="op">(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> i<span class="op">)</span></span>
<span id="cb22-2"><a href="#cb22-2"></a>  <span class="kw">noexcept</span><span class="op">(</span><span class="kw">noexcept</span><span class="op">(</span>ranges<span class="op">::</span>iter_move<span class="op">(</span>i<span class="op">.</span><em>current_</em><span class="op">)))</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_14" id="pnum_14">8</a></span> <em>Effects</em>: Equivalent to: <code class="sourceCode cpp"><span class="cf">return</span> ranges<span class="op">::</span>iter_move<span class="op">(</span>i<span class="op">.</span><em>current_</em><span class="op">)</span>;</code></p>
</blockquote>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">void</span> iter_swap<span class="op">(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> x, <span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> y<span class="op">)</span></span>
<span id="cb23-2"><a href="#cb23-2"></a>  <span class="kw">noexcept</span><span class="op">(</span><span class="kw">noexcept</span><span class="op">(</span>ranges<span class="op">::</span>iter_swap<span class="op">(</span>x<span class="op">.</span><em>current_</em>, y<span class="op">.</span><em>current_</em><span class="op">)))</span></span>
<span id="cb23-3"><a href="#cb23-3"></a>  <span class="kw">requires</span> indirectly_swappable<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span>V<span class="op">&gt;&gt;</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_15" id="pnum_15">9</a></span> <em>Effects</em>: Equivalent to: <code class="sourceCode cpp">ranges<span class="op">::</span>iter_swap<span class="op">(</span>x<span class="op">.</span><em>current_</em>, y<span class="op">.</span><em>current_</em><span class="op">)</span></code>.</p>
</blockquote>
</div>
<h4 class="unnumbered" data-number id="class-cache_latest_viewsentinel-range.cache.latest.sentinel">26.7.?.3 Class <code class="sourceCode cpp">cache_latest_view<span class="op">::</span><em>sentinel</em></code> [range.cache.latest.sentinel]<a href="#class-cache_latest_viewsentinel-range.cache.latest.sentinel" class="self-link"></a></h4>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2"></a>  <span class="kw">template</span><span class="op">&lt;</span>input_range V<span class="op">&gt;</span></span>
<span id="cb24-3"><a href="#cb24-3"></a>    <span class="kw">requires</span> view<span class="op">&lt;</span>V<span class="op">&gt;</span></span>
<span id="cb24-4"><a href="#cb24-4"></a>  <span class="kw">class</span> cache_latest_view<span class="op">&lt;</span>V<span class="op">&gt;::</span><em>sentinel</em> <span class="op">{</span></span>
<span id="cb24-5"><a href="#cb24-5"></a>    sentinel_t<span class="op">&lt;</span>V<span class="op">&gt;</span> <em>end_</em> <span class="op">=</span> sentinel_t<span class="op">&lt;</span>V<span class="op">&gt;()</span>;               <span class="co">// exposition only</span></span>
<span id="cb24-6"><a href="#cb24-6"></a></span>
<span id="cb24-7"><a href="#cb24-7"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> <em>sentinel</em><span class="op">(</span>cache_latest_view<span class="op">&amp;</span> parent<span class="op">)</span>;   <span class="co">// exposition only</span></span>
<span id="cb24-8"><a href="#cb24-8"></a></span>
<span id="cb24-9"><a href="#cb24-9"></a>  <span class="kw">public</span><span class="op">:</span></span>
<span id="cb24-10"><a href="#cb24-10"></a>    <em>sentinel</em><span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb24-11"><a href="#cb24-11"></a></span>
<span id="cb24-12"><a href="#cb24-12"></a>    <span class="kw">constexpr</span> sentinel_t<span class="op">&lt;</span>V<span class="op">&gt;</span> base<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb24-13"><a href="#cb24-13"></a></span>
<span id="cb24-14"><a href="#cb24-14"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> x, <span class="kw">const</span> <em>sentinel</em><span class="op">&amp;</span> y<span class="op">)</span>;</span>
<span id="cb24-15"><a href="#cb24-15"></a>    </span>
<span id="cb24-16"><a href="#cb24-16"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> range_difference_t<span class="op">&lt;</span>V<span class="op">&gt;</span> <span class="kw">operator</span><span class="op">-(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> x, <span class="kw">const</span> <em>sentinel</em><span class="op">&amp;</span> y<span class="op">)</span></span>
<span id="cb24-17"><a href="#cb24-17"></a>      <span class="kw">requires</span> sized_sentinel_for<span class="op">&lt;</span>sentinel_t<span class="op">&lt;</span>V<span class="op">&gt;</span>, iterator_t<span class="op">&lt;</span>V<span class="op">&gt;&gt;</span>;</span>
<span id="cb24-18"><a href="#cb24-18"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> range_difference_t<span class="op">&lt;</span>V<span class="op">&gt;</span> <span class="kw">operator</span><span class="op">-(</span><span class="kw">const</span> <em>sentinel</em><span class="op">&amp;</span> x, <span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> y<span class="op">)</span></span>
<span id="cb24-19"><a href="#cb24-19"></a>      <span class="kw">requires</span> sized_sentinel_for<span class="op">&lt;</span>sentinel_t<span class="op">&lt;</span>V<span class="op">&gt;</span>, iterator_t<span class="op">&lt;</span>V<span class="op">&gt;&gt;</span>;</span>
<span id="cb24-20"><a href="#cb24-20"></a>  <span class="op">}</span>;</span>
<span id="cb24-21"><a href="#cb24-21"></a><span class="op">}</span></span></code></pre></div>
<div>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1"></a><span class="kw">constexpr</span> <span class="kw">explicit</span> <em>sentinel</em><span class="op">(</span>cache_latest_view<span class="op">&amp;</span> parent<span class="op">)</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_16" id="pnum_16">1</a></span> <em>Effects</em>: Initializes <code class="sourceCode cpp"><em>end_</em></code> with <code class="sourceCode cpp">ranges<span class="op">::</span>end<span class="op">(</span>parent<span class="op">.</span><em>base_</em><span class="op">)</span></code>.</p>
</blockquote>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1"></a><span class="kw">constexpr</span> sentinel_t<span class="op">&lt;</span>V<span class="op">&gt;</span> base<span class="op">()</span> <span class="kw">const</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_17" id="pnum_17">2</a></span> <em>Returns:</em> <code class="sourceCode cpp"><em>end_</em></code>.</p>
</blockquote>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> x, <span class="kw">const</span> <em>sentinel</em><span class="op">&amp;</span> y<span class="op">)</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_18" id="pnum_18">3</a></span> <em>Returns:</em> <code class="sourceCode cpp">x<span class="op">.</span><em>current_</em> <span class="op">==</span> y<span class="op">.</span><em>end_</em></code>.</p>
</blockquote>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> range_difference_t<span class="op">&lt;</span>V<span class="op">&gt;</span> <span class="kw">operator</span><span class="op">-(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> x, <span class="kw">const</span> <em>sentinel</em><span class="op">&amp;</span> y<span class="op">)</span></span>
<span id="cb28-2"><a href="#cb28-2"></a>  <span class="kw">requires</span> sized_sentinel_for<span class="op">&lt;</span>sentinel_t<span class="op">&lt;</span>V<span class="op">&gt;</span>, iterator_t<span class="op">&lt;</span>V<span class="op">&gt;&gt;</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_19" id="pnum_19">4</a></span> <em>Returns:</em> <code class="sourceCode cpp">x<span class="op">.</span><em>current_</em> <span class="op">-</span> y<span class="op">.</span><em>end_</em></code>.</p>
</blockquote>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> range_difference_t<span class="op">&lt;</span>V<span class="op">&gt;</span> <span class="kw">operator</span><span class="op">-(</span><span class="kw">const</span> <em>sentinel</em><span class="op">&amp;</span> x, <span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> y<span class="op">)</span></span>
<span id="cb29-2"><a href="#cb29-2"></a>  <span class="kw">requires</span> sized_sentinel_for<span class="op">&lt;</span>sentinel_t<span class="op">&lt;</span>V<span class="op">&gt;</span>, iterator_t<span class="op">&lt;</span>V<span class="op">&gt;&gt;</span>;</span></code></pre></div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_20" id="pnum_20">5</a></span> <em>Returns:</em> <code class="sourceCode cpp">x<span class="op">.</span><em>end_</em> <span class="op">-</span> y<span class="op">.</span><em>current_</em></code>.</p>
</blockquote>
</div>
<h2 data-number="5.3" id="feature-test-macro"><span class="header-section-number">5.3</span> Feature-test macro<a href="#feature-test-macro" class="self-link"></a></h2>
<p>Add the following macro definition to <span>17.3.2 <a href="https://eel.is/c++draft/version.syn">[version.syn]</a></span>, header <code class="sourceCode cpp"><span class="op">&lt;</span>version<span class="op">&gt;</span></code> synopsis, with the value selected by the editor to reflect the date of adoption of this paper:</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1"></a><span class="pp">#define __cpp_lib_ranges_cache_latest </span><span class="dv">20</span><span class="er">XXXXL</span><span class="pp"> </span><span class="co">// also in &lt;ranges&gt;</span></span></code></pre></div>
<h1 data-number="6" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">6</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-N4971">
<p>[N4971] Thomas Köppe. 2023-12-18. Working Draft, Programming Languages — C++. <br />
<a href="https://wg21.link/n4971">https://wg21.link/n4971</a></p>
</div>
<div id="ref-P2760R1">
<p>[P2760R1] Barry Revzin. 2023-12-15. A Plan for C++26 Ranges. <br />
<a href="https://wg21.link/p2760r1">https://wg21.link/p2760r1</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
