<!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-05-21" />
  <title>views::cache_last</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_last</code></h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3138R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-05-21</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>
      SG1<br>
      LEWG<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_last</code> adaptor that caches the result of the last dereference of the underlying iterator. To support this adaptor, it also proposes an exception and a clarification to <span>16.4.6.10 <a href="https://wg21.link/res.on.data.races">[res.on.data.races]</a></span>.</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>R1: Limited the <span>16.4.6.10 <a href="https://wg21.link/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> 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>Relax <span>16.4.6.10 <a href="https://wg21.link/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://wg21.link/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 it applies to templated functions in the standard library, so this paper proposes a clarification.</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_last</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://wg21.link/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>
<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="clarifying-res.on.data.races"><span class="header-section-number">5.1</span> Clarifying [res.on.data.races]<a href="#clarifying-res.on.data.races" class="self-link"></a></h2>
<p>Edit <span>16.4.6.10 <a href="https://wg21.link/res.on.data.races">[res.on.data.races]</a></span> p1 as indicated:</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">1</a></span> This subclause specifies requirements that implementations shall meet to prevent data races. Every standard library function shall meet each requirement unless otherwise specified. Implementations may prevent data races in cases other than those specified below. <span class="diffins">For the purpose of applying these requirements to standard library templated functions, each operation on types dependent on a template argument is assumed to meet these requirements. <span class="note"><span>[ <em>Note 1:</em> </span>If a supplied operation does not meet these requirements, a data race can result, but the behavior is otherwise well-defined.<span> — <em>end note</em> ]</span></span></span></p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">2</a></span> A C++ standard library function shall not directly or indirectly access objects ([intro.multithread]) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function’s arguments, including <code class="sourceCode cpp"><span class="kw">this</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">3</a></span> A C++ standard library function shall not directly or indirectly modify objects (<span>6.9.2 <a href="https://wg21.link/intro.multithread">[intro.multithread]</a></span>) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function’s non-const arguments, including <code class="sourceCode cpp"><span class="kw">this</span></code>.</p>
<h2 data-number="5.2" id="addition-to-ranges"><span class="header-section-number">5.2</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>26.2 <a href="https://wg21.link/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.last], to input 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_last_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_last <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.3" id="cache_last"><span class="header-section-number">5.3</span> <code class="sourceCode cpp">cache_last</code><a href="#cache_last" class="self-link"></a></h2>
<p>Add the following subclause to <span>26.7 <a href="https://wg21.link/range.adaptors">[range.adaptors]</a></span>:</p>
<h3 class="unnumbered" data-number id="cache-last-view-range.cache.last">26.7.? Cache last view [range.cache.last]<a href="#cache-last-view-range.cache.last" class="self-link"></a></h3>
<h4 class="unnumbered" data-number id="overview-range.cache.last.overview">26.7.?.1 Overview [range.cache.last.overview]<a href="#overview-range.cache.last.overview" class="self-link"></a></h4>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">1</a></span> <code class="sourceCode cpp">cache_last_view</code> caches the last 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_5" id="pnum_5">2</a></span> The name <code class="sourceCode cpp">views<span class="op">::</span>cache_last</code> denotes a range adaptor object (<span>26.7.2 <a href="https://wg21.link/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_last<span class="op">(</span>E<span class="op">)</span></code> is expression-equivalent to <code class="sourceCode cpp">cache_last_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_last_view</code>. ]</span></p>
<h4 class="unnumbered" data-number id="class-template-cache_last_view-range.cache.last.view">26.7.?.2 Class template <code class="sourceCode cpp">cache_last_view</code> [range.cache.last.view]<a href="#class-template-cache_last_view-range.cache.last.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_last_view <span class="op">:</span> <span class="kw">public</span> view_interface<span class="op">&lt;</span>cache_last_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_last_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_last_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_last_view<span class="op">(</span>R<span class="op">&amp;&amp;)</span> <span class="op">-&gt;</span> cache_last_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_last_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_6" id="pnum_6">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_7" id="pnum_7">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_8" id="pnum_8">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_9" id="pnum_9">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_last_viewiterator-range.cache.last.iterator">26.7.?.3 Class <code class="sourceCode cpp">cache_last_view<span class="op">::</span><em>iterator</em></code> [range.cache.last.iterator]<a href="#class-cache_last_viewiterator-range.cache.last.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_last_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_last_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_last_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_last_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_10" id="pnum_10">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_11" id="pnum_11">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_12" id="pnum_12">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_13" id="pnum_13">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>   <span class="op">++</span><em>current_</em>;</span>
<span id="cb18-2"><a href="#cb18-2"></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-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_14" id="pnum_14">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_15" id="pnum_15">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_16" id="pnum_16">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://wg21.link/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_17" id="pnum_17">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_18" id="pnum_18">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_last_viewsentinel-range.cache.last.sentinel">26.7.?.3 Class <code class="sourceCode cpp">cache_last_view<span class="op">::</span><em>sentinel</em></code> [range.cache.last.sentinel]<a href="#class-cache_last_viewsentinel-range.cache.last.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_last_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_last_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 class="op">}</span>;</span>
<span id="cb24-16"><a href="#cb24-16"></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_last_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_19" id="pnum_19">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_20" id="pnum_20">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_21" id="pnum_21">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>
<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>
