<!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="2025-05-24" />
  <title>`any_view`</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.csl-block{margin-left: 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; }
      .sourceCode { overflow: visible; }
      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;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
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>
  <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">any_view</code></h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>D3411R3</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-05-24</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>
      SG9, LEWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Hui Xie<br>&lt;<a href="mailto:hui.xie1990@gmail.com" class="email">hui.xie1990@gmail.com</a>&gt;<br>
      Louis Dionne<br>&lt;<a href="mailto:ldionne.2@gmail.com" class="email">ldionne.2@gmail.com</a>&gt;<br>
      S. Levent Yilmaz<br>&lt;<a href="mailto:levent.yilmaz@gmail.com" class="email">levent.yilmaz@gmail.com</a>&gt;<br>
      Patrick Roberts<br>&lt;<a href="mailto:cpp@patrickroberts.dev" class="email">cpp@patrickroberts.dev</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#revision-history" id="toc-revision-history"><span class="toc-section-number">1</span> Revision History<span></span></a>
<ul>
<li><a href="#r3" id="toc-r3"><span class="toc-section-number">1.1</span> R3<span></span></a></li>
<li><a href="#r2" id="toc-r2"><span class="toc-section-number">1.2</span> R2<span></span></a></li>
<li><a href="#r1" id="toc-r1"><span class="toc-section-number">1.3</span> R1<span></span></a></li>
<li><a href="#r0" id="toc-r0"><span class="toc-section-number">1.4</span> R0<span></span></a></li>
</ul></li>
<li><a href="#abstract" id="toc-abstract"><span class="toc-section-number">2</span> Abstract<span></span></a></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">3</span> Motivation<span></span></a></li>
<li><a href="#design-space-and-prior-art" id="toc-design-space-and-prior-art"><span class="toc-section-number">4</span> Design Space and Prior
Art<span></span></a>
<ul>
<li><a href="#boost.range-boostrangesany_range" id="toc-boost.range-boostrangesany_range"><span class="toc-section-number">4.1</span> Boost.Range <code class="sourceCode cpp">boost<span class="op">::</span>ranges<span class="op">::</span>any_range</code><span></span></a></li>
<li><a href="#range-v3-rangesviewsany_view" id="toc-range-v3-rangesviewsany_view"><span class="toc-section-number">4.2</span> range-v3 <code class="sourceCode cpp">ranges<span class="op">::</span>views<span class="op">::</span>any_view</code><span></span></a></li>
</ul></li>
<li><a href="#proposed-design" id="toc-proposed-design"><span class="toc-section-number">5</span> Proposed
Design<span></span></a></li>
<li><a href="#alternative-design-for-template-parameters" id="toc-alternative-design-for-template-parameters"><span class="toc-section-number">6</span> Alternative Design for Template
Parameters<span></span></a>
<ul>
<li><a href="#alternative-design-1-variadic-named-template-parameters" id="toc-alternative-design-1-variadic-named-template-parameters"><span class="toc-section-number">6.1</span> Alternative Design 1: Variadic
Named Template Parameters<span></span></a></li>
<li><a href="#alternative-design-2-single-template-parameter-rangetraits" id="toc-alternative-design-2-single-template-parameter-rangetraits"><span class="toc-section-number">6.2</span> Alternative Design 2: Single
Template Parameter: RangeTraits<span></span></a></li>
<li><a href="#alternative-design-3-barrys-named-template-argument-approach" id="toc-alternative-design-3-barrys-named-template-argument-approach"><span class="toc-section-number">6.3</span> Alternative Design 3: Barry’s
Named Template Argument Approach<span></span></a></li>
<li><a href="#sg9-decision" id="toc-sg9-decision"><span class="toc-section-number">6.4</span> SG9 Decision<span></span></a></li>
</ul></li>
<li><a href="#other-design-considerations" id="toc-other-design-considerations"><span class="toc-section-number">7</span> Other Design
Considerations<span></span></a>
<ul>
<li><a href="#why-dont-follow-range-v3s-design-where-first-template-parameter-is-range_reference_t" id="toc-why-dont-follow-range-v3s-design-where-first-template-parameter-is-range_reference_t"><span class="toc-section-number">7.1</span> Why don’t follow range-v3’s design
where first template parameter is
<code class="sourceCode cpp">range_reference_t</code>?<span></span></a></li>
<li><a href="#name-of-the-any_view_options" id="toc-name-of-the-any_view_options"><span class="toc-section-number">7.2</span> Name of the
<code class="sourceCode cpp">any_view_options</code><span></span></a></li>
<li><a href="#constexpr-support" id="toc-constexpr-support"><span class="toc-section-number">7.3</span>
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
Support<span></span></a></li>
<li><a href="#move-only-view-support" id="toc-move-only-view-support"><span class="toc-section-number">7.4</span> Move-only
<code class="sourceCode cpp">view</code> Support<span></span></a></li>
<li><a href="#move-only-iterator-support" id="toc-move-only-iterator-support"><span class="toc-section-number">7.5</span> Move-only
<code class="sourceCode cpp">iterator</code>
Support<span></span></a></li>
<li><a href="#is-any_view_optionscontiguous-needed" id="toc-is-any_view_optionscontiguous-needed"><span class="toc-section-number">7.6</span> Is <code class="sourceCode cpp">any_view_options<span class="op">::</span>contiguous</code>
Needed ?<span></span></a></li>
<li><a href="#is-any_view-const-iterable" id="toc-is-any_view-const-iterable"><span class="toc-section-number">7.7</span> Is
<code class="sourceCode cpp">any_view</code>
const-iterable?<span></span></a></li>
<li><a href="#common_range-support" id="toc-common_range-support"><span class="toc-section-number">7.8</span>
<code class="sourceCode cpp">common_range</code>
support<span></span></a></li>
<li><a href="#borrowed_range-support" id="toc-borrowed_range-support"><span class="toc-section-number">7.9</span>
<code class="sourceCode cpp">borrowed_range</code>
support<span></span></a></li>
<li><a href="#valueless-state-of-any_view" id="toc-valueless-state-of-any_view"><span class="toc-section-number">7.10</span> Valueless state of
<code class="sourceCode cpp">any_view</code><span></span></a></li>
<li><a href="#abi-stability" id="toc-abi-stability"><span class="toc-section-number">7.11</span> ABI
Stability<span></span></a></li>
<li><a href="#performance" id="toc-performance"><span class="toc-section-number">7.12</span> Performance<span></span></a></li>
</ul></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">8</span> Implementation
Experience<span></span></a></li>
<li><a href="#wording" id="toc-wording"><span class="toc-section-number">9</span> Wording<span></span></a>
<ul>
<li><a href="#addition-to-ranges" id="toc-addition-to-ranges"><span class="toc-section-number">9.1</span> Addition to <code class="sourceCode cpp"><span class="op">&lt;</span>ranges<span class="op">&gt;</span></code><span></span></a></li>
<li><a href="#any_view" id="toc-any_view"><span class="toc-section-number">9.2</span>
<code class="sourceCode cpp">any_view</code><span></span></a></li>
</ul></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">10</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="revision-history"><span class="header-section-number">1</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<h2 data-number="1.1" id="r3"><span class="header-section-number">1.1</span> R3<a href="#r3" class="self-link"></a></h2>
<ul>
<li>Fix <code class="sourceCode cpp">contiguous</code> range</li>
</ul>
<h2 data-number="1.2" id="r2"><span class="header-section-number">1.2</span> R2<a href="#r2" class="self-link"></a></h2>
<ul>
<li>Add
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
support</li>
<li>Add initial wording</li>
<li>Move-only by default</li>
<li>Second reference implementation</li>
<li>Various fixes</li>
</ul>
<h2 data-number="1.3" id="r1"><span class="header-section-number">1.3</span> R1<a href="#r1" class="self-link"></a></h2>
<ul>
<li>Performance tests update
<ul>
<li>All benchmarks use -O3 (as requested in Wrocław)</li>
<li>For eager algorithms, do not use ranges at all (as requested in
Wrocław)</li>
<li>Add a new benchmark test case where
<code class="sourceCode cpp">vector</code> vs
<code class="sourceCode cpp">any_view</code> used in function
arguments</li>
</ul></li>
<li>Template parameters redesign
<ul>
<li><code class="sourceCode cpp">any_view<span class="op">&lt;</span>Foo<span class="op">&gt;</span></code>
and <code class="sourceCode cpp">any_view<span class="op">&lt;</span><span class="kw">const</span> Foo<span class="op">&gt;</span></code>
should just work</li>
<li>4 Different alternative designs</li>
</ul></li>
</ul>
<h2 data-number="1.4" id="r0"><span class="header-section-number">1.4</span> R0<a href="#r0" class="self-link"></a></h2>
<ul>
<li>Initial revision.</li>
</ul>
<h1 data-number="2" id="abstract"><span class="header-section-number">2</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>This paper proposes a new type-erased view: <code class="sourceCode cpp">std<span class="op">::</span>ranges<span class="op">::</span>any_view</code>.
That type-erased view allows customizing the traversal category of the
view, its value type and a few other properties. For example:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> MyClass <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>unordered_map<span class="op">&lt;</span>Key, Widget<span class="op">&gt;</span> widgets_;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>ranges<span class="op">::</span>any_view<span class="op">&lt;</span>Widget<span class="op">&gt;</span> getWidgets<span class="op">()</span>;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>ranges<span class="op">::</span>any_view<span class="op">&lt;</span>Widget<span class="op">&gt;</span> MyClass<span class="op">::</span>getWidgets<span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> widgets_ <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>values</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>                  <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>filter<span class="op">(</span>myFilter<span class="op">)</span>;</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h1 data-number="3" id="motivation"><span class="header-section-number">3</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>Since being merged into C++20, the Ranges library has gained an
increasingly rich and expressive set of views. For example,</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">// in MyClass.hpp</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> MyClass <span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>unordered_map<span class="op">&lt;</span>Key, Widget<span class="op">&gt;</span> widgets_;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> getWidgets<span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> widgets_ <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>values</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>                    <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>filter<span class="op">([](</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;){</span> <span class="co">/*...*/</span> <span class="op">})</span>;</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>While such use of ranges is exceedingly convenient, it has the
drawback of leaking implementation details into the interface. In this
example, the return type of the function essentially bakes the
implementation of the function into the interface.</p>
<p>In large applications, such liberal use of
<code class="sourceCode cpp">std<span class="op">::</span>ranges</code>
can lead to increased header dependencies and often a significant
compilation time penalty.</p>
<p>Attempts to separate the implementation into its own translation
unit, as is a common practice for non-templated code, are futile in this
situation. The return type of the above definition of
<code class="sourceCode cpp">getWidgets</code> is:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>ranges<span class="op">::</span>filter_view<span class="op">&lt;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>ranges<span class="op">::</span>elements_view<span class="op">&lt;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>ranges<span class="op">::</span>ref_view<span class="op">&lt;</span>std<span class="op">::</span>unordered_map<span class="op">&lt;</span>Key, Widget<span class="op">&gt;&gt;</span>,</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="dv">1</span><span class="op">&gt;</span>,</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  MyClass<span class="op">::</span>getWidgets<span class="op">()::&lt;</span>lambda<span class="op">(</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">:</span><span class="dv">11</span><span class="op">&amp;)&gt;</span> <span class="op">&gt;</span></span></code></pre></div>
<p>While this type is already difficult to spell once, it is much harder
and more brittle to maintain it as the implementation or the business
logic evolves. These challenges for templated interfaces are hardly
unique to ranges: the numerous string types in the language and lambdas
are some common examples that lead to similar challenges.</p>
<p>Type-erasure is a very popular technique to hide the concrete type of
an object behind a common interface, allowing polymorphic use of objects
of any type that model a given concept. In fact, it is a technique
commonly employed by the standard. <code class="sourceCode cpp">std<span class="op">::</span>string_view</code>
<code class="sourceCode cpp">std<span class="op">::</span>function</code> and
<code class="sourceCode cpp">std<span class="op">::</span>function_ref</code>,
and <code class="sourceCode cpp">std<span class="op">::</span>any</code>
are the type-erased facilities for the examples above.</p>
<p><code class="sourceCode cpp">std<span class="op">::</span>span<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
is another type-erasure utility recently added to the standard; and is
closely related to ranges in fact, by allowing type-erased
<em>reference</em> of any underlying <em>contiguous</em> range of
objects.</p>
<p>In this paper, we propose to extend the standard library with <code class="sourceCode cpp">std<span class="op">::</span>ranges<span class="op">::</span>any_view</code>,
which provides a convenient and generalized type-erasure facility to
hold any object of any type that satisfies the
<code class="sourceCode cpp">ranges<span class="op">::</span>view</code>
concept itself. <code class="sourceCode cpp">std<span class="op">::</span>ranges<span class="op">::</span>any_view</code>
also allows further refinement via customizable constraints on its
traversal categories and other range characteristics.</p>
<h1 data-number="4" id="design-space-and-prior-art"><span class="header-section-number">4</span> Design Space and Prior Art<a href="#design-space-and-prior-art" class="self-link"></a></h1>
<p>Designing a type like <code class="sourceCode cpp">any_view</code>
raises a lot of questions.</p>
<p>Let’s take <code class="sourceCode cpp">std<span class="op">::</span>function</code> as
an example. At first, its interface seems extremely simple: it provides
<code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code>
and users only need to configure the return type and argument types of
the function. In reality, <code class="sourceCode cpp">std<span class="op">::</span>function</code>
makes many other decisions for the user:</p>
<ul>
<li>Are <code class="sourceCode cpp">std<span class="op">::</span>function</code> and
the callable it contains
<code class="sourceCode cpp">copyable</code>?</li>
<li>Does <code class="sourceCode cpp">std<span class="op">::</span>function</code> own
the callable it contains?</li>
<li>Does <code class="sourceCode cpp">std<span class="op">::</span>function</code>
propagate const-ness?</li>
</ul>
<p>After answering all these questions we ended up with several
types:</p>
<ul>
<li><code class="sourceCode cpp">function</code></li>
<li><code class="sourceCode cpp">move_only_function</code></li>
<li><code class="sourceCode cpp">function_ref</code></li>
<li><code class="sourceCode cpp">copyable_function</code></li>
</ul>
<p>The design space of <code class="sourceCode cpp">any_view</code> is a
lot more complex than that:</p>
<ul>
<li>Is it an <code class="sourceCode cpp">input_range</code>,
<code class="sourceCode cpp">forward_range</code>,
<code class="sourceCode cpp">bidirectional_range</code>,
<code class="sourceCode cpp">random_access_range</code>, or a
<code class="sourceCode cpp">contiguous_range</code> ?</li>
<li>Is the range <code class="sourceCode cpp">copyable</code> ?</li>
<li>Is it a <code class="sourceCode cpp">sized_range</code> ?</li>
<li>Is it a <code class="sourceCode cpp">borrowed_range</code> ?</li>
<li>Is it a <code class="sourceCode cpp">common_range</code> ?</li>
<li>What is the <code class="sourceCode cpp">range_reference_t</code>
?</li>
<li>What is the <code class="sourceCode cpp">range_value_t</code> ?</li>
<li>What is the
<code class="sourceCode cpp">range_rvalue_reference_t</code> ?</li>
<li>What is the <code class="sourceCode cpp">range_difference_t</code>
?</li>
<li>Is the <code class="sourceCode cpp">range</code>
const-iterable?</li>
<li>Is the iterator <code class="sourceCode cpp">copyable</code> for
<code class="sourceCode cpp">input_iterator</code>?</li>
<li>Is the iterator equality comparable for
<code class="sourceCode cpp">input_iterator</code>?</li>
<li>Do the iterator and sentinel types satisfy <code class="sourceCode cpp">sized_sentinel_for<span class="op">&lt;</span>S, I<span class="op">&gt;</span></code>?</li>
</ul>
<p>We can easily get a combinatorial explosion of types if we follow the
same approach we did for <code class="sourceCode cpp">std<span class="op">::</span>function</code>.
Fortunately, there is prior art to help us guide the design.</p>
<h2 data-number="4.1" id="boost.range-boostrangesany_range"><span class="header-section-number">4.1</span> Boost.Range <code class="sourceCode cpp">boost<span class="op">::</span>ranges<span class="op">::</span>any_range</code><a href="#boost.range-boostrangesany_range" class="self-link"></a></h2>
<p>The type declaration is:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> Value</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  , <span class="kw">class</span> Traversal</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  , <span class="kw">class</span> Reference</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  , <span class="kw">class</span> Difference</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  , <span class="kw">class</span> Buffer <span class="op">=</span> any_iterator_default_buffer</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> any_range;</span></code></pre></div>
<p>Users will need to provide
<code class="sourceCode cpp">range_reference_t</code>,
<code class="sourceCode cpp">range_value_t</code> and
<code class="sourceCode cpp">range_difference_t</code>.
<code class="sourceCode cpp">Traversal</code> is equivalent to
<code class="sourceCode cpp">iterator_concept</code>, which decides the
traversal category of the range. Users don’t need to specify
<code class="sourceCode cpp">copyable</code>,
<code class="sourceCode cpp">borrowed_range</code> and
<code class="sourceCode cpp">common_range</code>, because all
Boost.Range ranges are <code class="sourceCode cpp">copyable</code>,
<code class="sourceCode cpp">borrowed_range</code> and
<code class="sourceCode cpp">common_range</code>.
<code class="sourceCode cpp">sized_range</code> and
<code class="sourceCode cpp">range_rvalue_reference_t</code> are not
considered in the design.</p>
<h2 data-number="4.2" id="range-v3-rangesviewsany_view"><span class="header-section-number">4.2</span> range-v3 <code class="sourceCode cpp">ranges<span class="op">::</span>views<span class="op">::</span>any_view</code><a href="#range-v3-rangesviewsany_view" class="self-link"></a></h2>
<p>The type declaration is:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="kw">class</span> category</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    none <span class="op">=</span> <span class="dv">0</span>,</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    input <span class="op">=</span> <span class="dv">1</span>,</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    forward <span class="op">=</span> <span class="dv">3</span>,</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>    bidirectional <span class="op">=</span> <span class="dv">7</span>,</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    random_access <span class="op">=</span> <span class="dv">15</span>,</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    mask <span class="op">=</span> random_access,</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    sized <span class="op">=</span> <span class="dv">16</span>,</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Ref, category Cat <span class="op">=</span> category<span class="op">::</span>input<span class="op">&gt;</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> any_view;</span></code></pre></div>
<p>Here <code class="sourceCode cpp">Cat</code> handles both the
traversal category and <code class="sourceCode cpp">sized_range</code>.
<code class="sourceCode cpp">Ref</code> is the
<code class="sourceCode cpp">range_reference_t</code>. It does not allow
users to configure the
<code class="sourceCode cpp">range_value_t</code>,
<code class="sourceCode cpp">range_difference_t</code>,
<code class="sourceCode cpp">borrowed_range</code> and
<code class="sourceCode cpp">common_range</code>.
<code class="sourceCode cpp">copyable</code> is mandatory in
range-v3.</p>
<h1 data-number="5" id="proposed-design"><span class="header-section-number">5</span> Proposed Design<a href="#proposed-design" class="self-link"></a></h1>
<p>This paper proposes the following interface:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="kw">enum</span> <span class="kw">class</span> any_view_options <span class="op">{</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    input <span class="op">=</span> <span class="dv">1</span>,</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>    forward <span class="op">=</span> <span class="dv">3</span>,</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    bidirectional <span class="op">=</span> <span class="dv">7</span>,</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>    random_access <span class="op">=</span> <span class="dv">15</span>,</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>    contiguous <span class="op">=</span> <span class="dv">31</span>,</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    sized <span class="op">=</span> <span class="dv">32</span>,</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>    borrowed <span class="op">=</span> <span class="dv">64</span>,</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>    copyable <span class="op">=</span> <span class="dv">128</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">struct</span> <em>rvalue-ref</em> <span class="op">{</span> <span class="kw">using</span> type <span class="op">=</span> T; <span class="op">}</span>;</span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">struct</span> <em>rvalue-ref</em><span class="op">&lt;</span>T<span class="op">&amp;&gt;</span> <span class="op">{</span> <span class="kw">using</span> type <span class="op">=</span> T <span class="op">&amp;&amp;</span>; <span class="op">}</span>;</span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">using</span> <em>rvalue-ref-t</em> <span class="op">=</span> <em>rvalue-ref</em><span class="op">&lt;</span>T<span class="op">&gt;::</span>type;</span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Element,</span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>          any_view_options Opts <span class="op">=</span> any_view_options<span class="op">::</span>input,</span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> Ref <span class="op">=</span> Element <span class="op">&amp;</span>,</span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> RValueRef <span class="op">=</span> <em>rvalue-ref-t</em><span class="op">&lt;</span>Ref<span class="op">&gt;</span>,</span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> Diff <span class="op">=</span> <span class="dt">ptrdiff_t</span><span class="op">&gt;</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> any_view;</span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Element, any_view_options Opts, <span class="kw">class</span> Ref, <span class="kw">class</span> RValueRef,</span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> Diff<span class="op">&gt;</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">bool</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a>    enable_borrowed_range<span class="op">&lt;</span>any_view<span class="op">&lt;</span>Element, Opts, Ref, RValueRef, Diff<span class="op">&gt;&gt;</span> <span class="op">=</span></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true" tabindex="-1"></a>        <span class="dt">bool</span><span class="op">(</span>Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>borrowed<span class="op">)</span>;</span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="co">// namespace std::ranges</span></span></code></pre></div>
<p>The intent is that users can select various desired properties of the
<code class="sourceCode cpp">any_view</code> by <code class="sourceCode cpp">bitwise<span class="op">-</span><span class="kw">or</span></code>ing
them. For example:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView <span class="op">=</span> std<span class="op">::</span>ranges<span class="op">::</span>any_view<span class="op">&lt;</span>Widget, </span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>                                    std<span class="op">::</span>ranges<span class="op">::</span>any_view_options<span class="op">::</span>bidirectional <span class="op">|</span> </span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>                                    std<span class="op">::</span>ranges<span class="op">::</span>any_view_options<span class="op">::</span>sized<span class="op">&gt;</span>;</span></code></pre></div>
<h1 data-number="6" id="alternative-design-for-template-parameters"><span class="header-section-number">6</span> Alternative Design for Template
Parameters<a href="#alternative-design-for-template-parameters" class="self-link"></a></h1>
<p>In Wrocław meeting, one important point was made: The majority of the
use case of <code class="sourceCode cpp">any_view</code> is to use it as
a function parameter in the API boundary.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>Bar algo<span class="op">(</span>any_view<span class="op">&lt;</span>Foo<span class="op">&gt;)</span>;</span></code></pre></div>
<p>And in most of cases, the implementation of
<code class="sourceCode cpp">algo</code> only iterate over the range
once. The design should make it easy to specify an
“<code class="sourceCode cpp">input_range</code> only”
<code class="sourceCode cpp">view</code>, and sometimes “read-only”
access to the elements (a
<code class="sourceCode cpp"><span class="kw">const</span></code>
reference element type). That is,</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>any_view<span class="op">&lt;</span>Foo<span class="op">&gt;</span>; <span class="co">// should be an input_range where the range_reference_t is Foo&amp;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>any_view<span class="op">&lt;</span><span class="kw">const</span> Foo<span class="op">&gt;</span>; <span class="co">// should be an input_range where the range_reference_t is const Foo&amp;</span></span></code></pre></div>
<p>With the proposed design, the above two use cases would work. Even
though there are lots of template parameters, we do not expect users to
specify them often because the default would work for majority of the
use cases.</p>
<h2 data-number="6.1" id="alternative-design-1-variadic-named-template-parameters"><span class="header-section-number">6.1</span> Alternative Design 1: Variadic
Named Template Parameters<a href="#alternative-design-1-variadic-named-template-parameters" class="self-link"></a></h2>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> any_view_options <span class="op">{</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">&gt;</span> <span class="kw">struct</span> iterator_concept;</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">&gt;</span> <span class="kw">struct</span> reference_type;</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">&gt;</span> <span class="kw">struct</span> value_type;</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">&gt;</span> <span class="kw">struct</span> difference_type;</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">&gt;</span> <span class="kw">struct</span> rvalue_reference_type;</span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span> <span class="kw">struct</span> sized;</span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span> <span class="kw">struct</span> move_only;</span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span><span class="op">&gt;</span> <span class="kw">struct</span> borrowed;</span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="co">// any_view_options</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Element, <span class="kw">class</span><span class="op">...</span> Options<span class="op">&gt;</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> any_view;</span></code></pre></div>
<p>With this design, the two main use cases would still work</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView1 <span class="op">=</span> any_view<span class="op">&lt;</span>Foo<span class="op">&gt;</span>; <span class="co">// should be an input_range where the range_reference_t is Foo&amp;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView2 <span class="op">=</span> any_view<span class="op">&lt;</span><span class="kw">const</span> Foo<span class="op">&gt;</span>; <span class="co">// should be an input_range where the range_reference_t is const Foo&amp;</span></span></code></pre></div>
<p>If the default options do not work, users can specify the options in
this way:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <span class="kw">namespace</span> std<span class="op">::</span>ranges<span class="op">::</span>any_view_options;</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView3 <span class="op">=</span> std<span class="op">::</span>ranges<span class="op">::</span>any_view<span class="op">&lt;</span>Foo, </span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>                                      iterator_concept<span class="op">&lt;</span>std<span class="op">::</span>contiguous_iterator_tag<span class="op">&gt;</span>,</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>                                      reference_type<span class="op">&lt;</span>Foo<span class="op">&gt;</span>,</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>                                      sized<span class="op">&lt;</span><span class="kw">true</span><span class="op">&gt;</span>,</span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>                                      borrowed<span class="op">&lt;</span><span class="kw">true</span><span class="op">&gt;&gt;</span>;</span></code></pre></div>
<p>The benefits of this approach are</p>
<ul>
<li>Each parameter is named</li>
<li>Users do not need to specify the template parameters in a specific
order</li>
<li>Users can skip few template parameters if they need to customize the
“last” template option</li>
</ul>
<p>An implementation of this approach would look like this: <a href="https://godbolt.org/z/qdnoE7Mb9">link</a></p>
<p>However, we believe that this overcomplicates the design.</p>
<h2 data-number="6.2" id="alternative-design-2-single-template-parameter-rangetraits"><span class="header-section-number">6.2</span> Alternative Design 2: Single
Template Parameter: RangeTraits<a href="#alternative-design-2-single-template-parameter-rangetraits" class="self-link"></a></h2>
<p>In Wrocław meeting, one feedback we had was to explore the options to
have “single expansion point”, i.e not to have too many template
parameters</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> default_range_traits <span class="op">{}</span>;</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Element, <span class="kw">class</span> RangeTraits <span class="op">=</span> default_range_traits<span class="op">&gt;</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> any_view;</span></code></pre></div>
<p>In the <code class="sourceCode cpp">RangeTraits</code>, the user can
define aliases to customize
<code class="sourceCode cpp">iterator_concept</code>,
<code class="sourceCode cpp">reference_type</code> etc, and define <code class="sourceCode cpp"><span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span></code>
variables to customize <code class="sourceCode cpp">sized</code>,
<code class="sourceCode cpp">move_only</code> etc. If an alias or <code class="sourceCode cpp"><span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span></code>
variable is missing, the default type or value will be used.</p>
<p>With this design, the two main use cases would still work</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView1 <span class="op">=</span> any_view<span class="op">&lt;</span>Foo<span class="op">&gt;</span>; <span class="co">// should be an input_range where the range_reference_t is Foo&amp;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView2 <span class="op">=</span> any_view<span class="op">&lt;</span><span class="kw">const</span> Foo<span class="op">&gt;</span>; <span class="co">// should be an input_range where the range_reference_t is const Foo&amp;</span></span></code></pre></div>
<p>If the default options do not work, users can specify the options in
this way:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> MyTraits <span class="op">{</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> iterator_concept <span class="op">=</span> std<span class="op">::</span>contiguous_iterator_tag;</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> reference <span class="op">=</span> <span class="dt">int</span>;</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span> sized <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> move_only <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView3 <span class="op">=</span> any_view<span class="op">&lt;</span><span class="dt">int</span>, MyTraits<span class="op">&gt;</span>;</span></code></pre></div>
<p>The benefits of this approach are</p>
<ul>
<li>Each option is named</li>
<li>Users do not need to specify the template parameters in a specific
order</li>
<li>Users can skip any options if they can use the default values</li>
</ul>
<p>An implementation of this approach would look like this: <a href="https://godbolt.org/z/596avP8T5">link</a></p>
<p>However, every time an user needs to customize anything, they need to
define a
<code class="sourceCode cpp"><span class="kw">struct</span></code>,
which is verbose and inconvenient.</p>
<h3 data-number="6.2.1" id="optional-add-on-to-rangetraits"><span class="header-section-number">6.2.1</span> Optional add-on to
<code class="sourceCode cpp">RangeTraits</code><a href="#optional-add-on-to-rangetraits" class="self-link"></a></h3>
<p>If we decided to go with this alternative, we could have a utility
that deduces the traits from another range.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Range<span class="op">&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> range_traits <span class="op">{</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator_concept <span class="op">=</span> <span class="co">/* see-below */</span>;</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> reference_type <span class="op">=</span> range_reference_t<span class="op">&lt;</span>Range<span class="op">&gt;</span>;</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> value_type <span class="op">=</span> range_value_t<span class="op">&lt;</span>Range<span class="op">&gt;</span>;</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> rvalue_reference_type <span class="op">=</span> range_rvalue_reference_t<span class="op">&lt;</span>Range<span class="op">&gt;</span>;</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> difference_type <span class="op">=</span> range_difference_t<span class="op">&lt;</span>Range<span class="op">&gt;</span>;</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span> sized <span class="op">=</span> sized_range<span class="op">&lt;</span>Range<span class="op">&gt;</span>;</span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span> move_only <span class="op">=</span> <span class="op">!</span>copyable<span class="op">&lt;</span>decay_t<span class="op">&lt;</span>Range<span class="op">&gt;&gt;</span>;</span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span> borrowed <span class="op">=</span> borrowed_range<span class="op">&lt;</span>Range<span class="op">&gt;</span>;</span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="co">// MyView4 is a contiguous, sized, copyable, non-borrowed int&amp; range </span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView4 <span class="op">=</span> any_view<span class="op">&lt;</span><span class="dt">int</span>, range_traits<span class="op">&lt;</span>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;&gt;&gt;</span>;</span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a><span class="co">// MyView5 is a contiguous, sized, copyable, non-borrowed const int&amp; range </span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView5 <span class="op">=</span> any_view<span class="op">&lt;</span><span class="kw">const</span> <span class="dt">int</span>, range_traits<span class="op">&lt;</span><span class="kw">const</span> std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;&gt;&gt;</span>;</span></code></pre></div>
<p>An implementation of this approach would look like this: <a href="https://godbolt.org/z/co1Kdsra3">link</a></p>
<h2 data-number="6.3" id="alternative-design-3-barrys-named-template-argument-approach"><span class="header-section-number">6.3</span> Alternative Design 3: Barry’s
Named Template Argument Approach<a href="#alternative-design-3-barrys-named-template-argument-approach" class="self-link"></a></h2>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> type_t <span class="op">{</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> type_t<span class="op">&lt;</span>T<span class="op">&gt;</span> type<span class="op">{}</span>;</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Ref,</span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> IterConcept <span class="op">=</span> input_iterator_tag,</span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> Value <span class="op">=</span> decay_t<span class="op">&lt;</span>Ref<span class="op">&gt;</span>,</span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> RValueRef <span class="op">=</span> remove_reference_t<span class="op">&lt;</span>Ref<span class="op">&gt;&amp;&amp;</span>,</span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> Difference <span class="op">=</span> <span class="dt">ptrdiff_t</span><span class="op">&gt;</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> any_view_options <span class="op">{</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>    type_t<span class="op">&lt;</span>Ref<span class="op">&gt;</span> reference_type;</span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>    type_t<span class="op">&lt;</span>IterConcept<span class="op">&gt;</span> iterator_concept <span class="op">=</span> <span class="op">{}</span>;</span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> sized <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> move_only <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> borrowed <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>    type_t<span class="op">&lt;</span>Value<span class="op">&gt;</span> value_type;</span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a>    type_t<span class="op">&lt;</span>RValueRef<span class="op">&gt;</span> rvalue_reference_type;</span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a>    type_t<span class="op">&lt;</span>Difference<span class="op">&gt;</span> difference_type;</span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Element, any_view_options options <span class="op">=</span> <span class="op">{.</span>reference_type <span class="op">=</span> type<span class="op">&lt;</span>Element<span class="op">&amp;&gt;}&gt;</span></span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> any_view;</span></code></pre></div>
<p>This is inspired by Barry’s <a href="https://brevzin.github.io/c++/2019/12/02/named-arguments/">blog
post</a>. Thanks to designated initializers and generated CTAD, the user
code is extremely readable</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView1 <span class="op">=</span> any_view<span class="op">&lt;</span>Foo<span class="op">&gt;</span>; <span class="co">// should be an input_range where the range_reference_t is Foo&amp;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView2 <span class="op">=</span> any_view<span class="op">&lt;</span><span class="kw">const</span> Foo<span class="op">&gt;</span>; <span class="co">// should be an input_range where the range_reference_t is const Foo&amp;</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView3 <span class="op">=</span> any_view<span class="op">&lt;</span><span class="dt">int</span>, <span class="op">{.</span>reference_type <span class="op">=</span> type<span class="op">&lt;</span><span class="dt">int</span><span class="op">&amp;&gt;</span>,</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>                               <span class="op">.</span>iterator_concept <span class="op">=</span> type<span class="op">&lt;</span>std<span class="op">::</span>contiguous_iterator_tag<span class="op">&gt;</span>,</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>                               <span class="op">.</span>value_type <span class="op">=</span> type<span class="op">&lt;</span><span class="dt">long</span><span class="op">&gt;}&gt;</span>;</span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyView4 <span class="op">=</span> any_view<span class="op">&lt;</span><span class="dt">int</span>, <span class="op">{.</span>reference_type <span class="op">=</span> type<span class="op">&lt;</span><span class="dt">int</span><span class="op">&amp;&gt;</span>,</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>                               <span class="op">.</span>iterator_concept <span class="op">=</span> type<span class="op">&lt;</span>std<span class="op">::</span>contiguous_iterator_tag<span class="op">&gt;</span>,</span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>                               <span class="op">.</span>sized <span class="op">=</span> <span class="kw">true</span>,</span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>                               <span class="op">.</span>borrowed <span class="op">=</span> <span class="kw">true</span>,</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>                               <span class="op">.</span>value_type <span class="op">=</span> type<span class="op">&lt;</span><span class="dt">long</span><span class="op">&gt;}&gt;</span>;                        </span></code></pre></div>
<p>Each option is named and user can skip parameters if they want to use
the default. However, the user has to follow the same order of the
options that are defined in
<code class="sourceCode cpp">any_view_options</code>.</p>
<p>An implementation of this approach would look like this: <a href="https://godbolt.org/z/4dGYneWxx">link</a></p>
<h2 data-number="6.4" id="sg9-decision"><span class="header-section-number">6.4</span> SG9 Decision<a href="#sg9-decision" class="self-link"></a></h2>
<p>In Hagenberg, SG9 voted these designs</p>
<blockquote>
<p>I like the following template parameter design:</p>
<ul>
<li>Proposed in P3411R1 (flags + defaulted template parameters)</li>
<li>Alternative 1 (variadic named template parameters)</li>
<li>Alternative 2 (custom traits with potentially some standard library
provided default traits (e.g. the tags))</li>
<li>Alternative 3 (options aggregate type using type as
values/reflection and designated initializers)</li>
</ul>
</blockquote>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Option</strong>
</div></th>
<th><div style="text-align:center">
<strong>Approval votes</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Proposed</td>
<td>10</td>
</tr>
<tr class="even">
<td>Alternative 1</td>
<td>5</td>
</tr>
<tr class="odd">
<td>Alternative 2</td>
<td>5</td>
</tr>
<tr class="even">
<td>Alternative 3</td>
<td>4</td>
</tr>
</tbody>
</table>
<p>SG9 Recommended moving forward with the proposed design.</p>
<h1 data-number="7" id="other-design-considerations"><span class="header-section-number">7</span> Other Design Considerations<a href="#other-design-considerations" class="self-link"></a></h1>
<h2 data-number="7.1" id="why-dont-follow-range-v3s-design-where-first-template-parameter-is-range_reference_t"><span class="header-section-number">7.1</span> Why don’t follow range-v3’s
design where first template parameter is
<code class="sourceCode cpp">range_reference_t</code>?<a href="#why-dont-follow-range-v3s-design-where-first-template-parameter-is-range_reference_t" class="self-link"></a></h2>
<p>If the first template parameter is
<code class="sourceCode cpp">Ref</code>, we have:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Ref,</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>          any_view_options Opts <span class="op">=</span> any_view_options<span class="op">::</span>input,</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> Value <span class="op">=</span> remove_cvref_t<span class="op">&lt;</span>Ref<span class="op">&gt;&gt;</span></span></code></pre></div>
<p>For a range with a reference to
<code class="sourceCode cpp">T</code>, one would write</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>any_view<span class="op">&lt;</span>T<span class="op">&amp;&gt;</span></span></code></pre></div>
<p>And for a
<code class="sourceCode cpp"><span class="kw">const</span></code>
reference to <code class="sourceCode cpp">T</code>, one would write</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>any_view<span class="op">&lt;</span><span class="kw">const</span> T<span class="op">&amp;&gt;</span></span></code></pre></div>
<p>However, it is possible that the user uses <code class="sourceCode cpp">any_view<span class="op">&lt;</span>string<span class="op">&gt;</span></code>
without realizing that they specified the reference type and they now
make a copy of the <code class="sourceCode cpp">string</code> every time
when the iterator is dereferenced.</p>
<h2 data-number="7.2" id="name-of-the-any_view_options"><span class="header-section-number">7.2</span> Name of the
<code class="sourceCode cpp">any_view_options</code><a href="#name-of-the-any_view_options" class="self-link"></a></h2>
<p><code class="sourceCode cpp">range<span class="op">-</span>v3</code>
uses the name <code class="sourceCode cpp">category</code> for the
category enumeration type. However, the authors believe that the name
<code class="sourceCode cpp">std<span class="op">::</span>ranges<span class="op">::</span>category</code>
is too general and it should be reserved for more general purpose
utility in ranges library. Therefore, the authors recommend a more
specific name: <code class="sourceCode cpp">any_view_options</code>.</p>
<h2 data-number="7.3" id="constexpr-support"><span class="header-section-number">7.3</span>
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
Support<a href="#constexpr-support" class="self-link"></a></h2>
<p>We require
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
because there is no strong reason not to provide it. Even when providing
SBO at runtime, there is no need to provide such an optimization at
compile-time as well, given that the conditions for the optimization are
implementation-dependent, and experience shows this support is easy
enough to add. Both of our two reference implementations have proper
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
support. SG9 also recommended in Hagenberg to support
<code class="sourceCode cpp"><span class="kw">constexpr</span></code></p>
<h2 data-number="7.4" id="move-only-view-support"><span class="header-section-number">7.4</span> Move-only
<code class="sourceCode cpp">view</code> Support<a href="#move-only-view-support" class="self-link"></a></h2>
<p>Move-only <code class="sourceCode cpp">view</code> is worth
supporting as we generally support them in
<code class="sourceCode cpp">ranges</code>. We propose to have a
configuration template parameter <code class="sourceCode cpp">any_view_options<span class="op">::</span>copyable</code>
to make the <code class="sourceCode cpp">any_view</code> conditionally
copyable. This removes the need to have another type as we did for
<code class="sourceCode cpp">move_only_function</code>. We also propose
that by default, <code class="sourceCode cpp">any_view</code> is
move-only and to make it copyable, the user needs to explicitly provide
this template parameter <code class="sourceCode cpp">any_view_options<span class="op">::</span>copyable</code>.
On R1 version, this paper proposed to make
<code class="sourceCode cpp">any_view</code> copyable by default.</p>
<p>In Hagenberg, SG9 recommended to make it move-only by default with
the votes:</p>
<blockquote>
<p>As proposed, any_view<T> is copyable by default, requiring a flag to
allow type-erasing move-only types. We want to change it to be move-only
by default, requiring a flag to make it copyable and prohibit
type-erasure of move-only types.</p>
</blockquote>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th><div style="text-align:center">
<strong>F</strong>
</div></th>
<th><div style="text-align:center">
<strong>N</strong>
</div></th>
<th><div style="text-align:center">
<strong>A</strong>
</div></th>
<th><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>4</td>
<td>5</td>
<td>1</td>
<td>0</td>
<td>1</td>
</tr>
</tbody>
</table>
<h2 data-number="7.5" id="move-only-iterator-support"><span class="header-section-number">7.5</span> Move-only
<code class="sourceCode cpp">iterator</code> Support<a href="#move-only-iterator-support" class="self-link"></a></h2>
<p>In this proposal, <code class="sourceCode cpp">any_view<span class="op">::</span>iterator</code>
is an exposition-only type. It is not worth making this
<code class="sourceCode cpp">iterator</code> configurable. If the
<code class="sourceCode cpp">iterator</code> is only
<code class="sourceCode cpp">input_iterator</code>, we can also make it
a move-only iterator. There is no need to make it copyable. Existing
algorithms that take “input only” iterators already know that they
cannot copy them.</p>
<h2 data-number="7.6" id="is-any_view_optionscontiguous-needed"><span class="header-section-number">7.6</span> Is <code class="sourceCode cpp">any_view_options<span class="op">::</span>contiguous</code>
Needed ?<a href="#is-any_view_optionscontiguous-needed" class="self-link"></a></h2>
<p><code class="sourceCode cpp">contiguous_range</code> is still useful
to support even though we have already
<code class="sourceCode cpp">std<span class="op">::</span>span</code>.
But <code class="sourceCode cpp">span</code> is non-owning and
<code class="sourceCode cpp">any_view</code> owns the underlying
<code class="sourceCode cpp">view</code>.</p>
<h2 data-number="7.7" id="is-any_view-const-iterable"><span class="header-section-number">7.7</span> Is
<code class="sourceCode cpp">any_view</code> const-iterable?<a href="#is-any_view-const-iterable" class="self-link"></a></h2>
<p>We cannot make <code class="sourceCode cpp">any_view</code>
unconditionally const-iterable. If we did,
<code class="sourceCode cpp">views</code> with cache-on-begin, like
<code class="sourceCode cpp">filter_view</code> and
<code class="sourceCode cpp">drop_while_view</code> could no longer be
put into an <code class="sourceCode cpp">any_view</code>.</p>
<p>One option would be to make
<code class="sourceCode cpp">any_view</code> conditionally
const-iterable, via a configuration template parameter. However, this
would make the whole interface much more complicated, as each
configuration template parameter would need to be duplicated. Indeed,
associated types like <code class="sourceCode cpp">Ref</code> and
<code class="sourceCode cpp">RValueRef</code> can be different between
<code class="sourceCode cpp"><span class="kw">const</span></code> and
non-<code class="sourceCode cpp"><span class="kw">const</span></code>
iterators.</p>
<p>For simplicity, the authors propose to make
<code class="sourceCode cpp">any_view</code> unconditionally
non-const-iterable.</p>
<h2 data-number="7.8" id="common_range-support"><span class="header-section-number">7.8</span>
<code class="sourceCode cpp">common_range</code> support<a href="#common_range-support" class="self-link"></a></h2>
<p>Unconditionally making <code class="sourceCode cpp">any_view</code> a
<code class="sourceCode cpp">common_range</code> is not an option. This
would exclude most of the Standard Library
<code class="sourceCode cpp">view</code>s. Adding a configuration
template parameter to make <code class="sourceCode cpp">any_view</code>
conditionally <code class="sourceCode cpp">common_range</code> is
overkill. After all, if users need
<code class="sourceCode cpp">common_range</code>, they can use <code class="sourceCode cpp">my_any_view <span class="op">|</span> views<span class="op">::</span>common</code>.
Furthermore, supporting this turns out to add substantial complexity in
the implementation. The authors believe that adding
<code class="sourceCode cpp">common_range</code> support is not worth
the added complexity. This is also confirmed with the votes in SG9 in
Hagenberg.</p>
<blockquote>
<p>As proposed, any_view<T> is never a common range. We want to have a
flag to make it a common range if that flag is set.</p>
</blockquote>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th><div style="text-align:center">
<strong>F</strong>
</div></th>
<th><div style="text-align:center">
<strong>N</strong>
</div></th>
<th><div style="text-align:center">
<strong>A</strong>
</div></th>
<th><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>1</td>
<td>4</td>
<td>2</td>
<td>0</td>
</tr>
</tbody>
</table>
<h2 data-number="7.9" id="borrowed_range-support"><span class="header-section-number">7.9</span>
<code class="sourceCode cpp">borrowed_range</code> support<a href="#borrowed_range-support" class="self-link"></a></h2>
<p>Having support for <code class="sourceCode cpp">borrowed_range</code>
is simple enough:</p>
<ul>
<li><ol type="1">
<li>Add a template configuration parameter</li>
</ol></li>
<li><ol start="2" type="1">
<li>Specialise the
<code class="sourceCode cpp">enable_borrowed_range</code> if the
template parameter is set to
<code class="sourceCode cpp"><span class="kw">true</span></code></li>
</ol></li>
</ul>
<p>Therefore, we recommend conditional support for
<code class="sourceCode cpp">borrowed_range</code>. However, since
<code class="sourceCode cpp">borrowed_range</code> is not a very useful
concept in general, this design point is open for discussion.</p>
<h2 data-number="7.10" id="valueless-state-of-any_view"><span class="header-section-number">7.10</span> Valueless state of
<code class="sourceCode cpp">any_view</code><a href="#valueless-state-of-any_view" class="self-link"></a></h2>
<p>We propose providing the strong exception safety guarantee in the
following operations: swap, copy-assignment, move-assignment and
move-construction. This means that if the operation fails, the two
<code class="sourceCode cpp">any_view</code> objects will be in their
original states. If the underlying view’s move constructor (or
move-assignment operator) is not
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>,
the only way to achieve the strong exception safety guarantee is to
avoid calling these operations altogether, which requires
<code class="sourceCode cpp">any_view</code> to hold its underlying
object on the heap so it can implement these operations by swapping
pointers. This means that any implementation of
<code class="sourceCode cpp">any_view</code> will have an empty state,
and a “moved-from” heap allocated
<code class="sourceCode cpp">any_view</code> will be in that state.</p>
<h2 data-number="7.11" id="abi-stability"><span class="header-section-number">7.11</span> ABI Stability<a href="#abi-stability" class="self-link"></a></h2>
<p>As a type intended to exist at ABI boundaries, ensuring the ABI
stability of <code class="sourceCode cpp">any_view</code> is extremely
important. However, since almost any change to the API of
<code class="sourceCode cpp">any_view</code> will require a modification
to the vtable, this makes <code class="sourceCode cpp">any_view</code>
somewhat fragile to incremental evolution. This drawback is shared by
all C++ types that live at ABI boundaries, and while we don’t think this
impacts the livelihood of <code class="sourceCode cpp">any_view</code>,
this evolutionary challenge should be kept in mind by WG21.</p>
<h2 data-number="7.12" id="performance"><span class="header-section-number">7.12</span> Performance<a href="#performance" class="self-link"></a></h2>
<p>One of the major concerns of using type erasure is the performance
cost of indirect function calls and their impact on the ability for the
compiler to perform optimizations. With
<code class="sourceCode cpp">any_view</code>, every iteration will have
three indirect function calls:</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="op">++</span>it;</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>it <span class="op">!=</span> last;</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="op">*</span>it;</span></code></pre></div>
<p>While it may at first seem prohibitive, it is useful to remember the
context in which <code class="sourceCode cpp">any_view</code> is used
and what the alternatives to it are.</p>
<p>The following benchmarks were compiled with clang 20 with libc++,
with -O3, run on APPLE M4 MAX CPU with 16 cores. We have done the same
benchmarks on a 8 core Intel CPU and they have very similar results.</p>
<h3 data-number="7.12.1" id="a-naive-micro-benchmark-iteration-over-vector-vs-any_view"><span class="header-section-number">7.12.1</span> A naive micro benchmark:
iteration over <code class="sourceCode cpp">vector</code> vs
<code class="sourceCode cpp">any_view</code><a href="#a-naive-micro-benchmark-iteration-over-vector-vs-any_view" class="self-link"></a></h3>
<p>Naively, one would be tempted to benchmark the cost of iterating over
a
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
and to compare it with the cost of iterating over
<code class="sourceCode cpp">any_view</code>. For example, the following
code:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector v <span class="op">=</span> std<span class="op">::</span>views<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, state<span class="op">.</span>range<span class="op">(</span><span class="dv">0</span><span class="op">))</span> <span class="op">|</span> std<span class="op">::</span>ranges<span class="op">::</span>to<span class="op">&lt;</span>std<span class="op">::</span>vector<span class="op">&gt;()</span>;</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> _ <span class="op">:</span> state<span class="op">)</span> <span class="op">{</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> i <span class="op">:</span> v<span class="op">)</span> <span class="op">{</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>      benchmark<span class="op">::</span>DoNotOptimize<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span></code></pre></div>
<p>vs</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector v <span class="op">=</span> std<span class="op">::</span>views<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, state<span class="op">.</span>range<span class="op">(</span><span class="dv">0</span><span class="op">))</span> <span class="op">|</span> std<span class="op">::</span>ranges<span class="op">::</span>to<span class="op">&lt;</span>std<span class="op">::</span>vector<span class="op">&gt;()</span>;</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>ranges<span class="op">::</span>any_view<span class="op">&lt;</span><span class="dt">int</span><span class="op">&amp;&gt;</span> av<span class="op">(</span>std<span class="op">::</span>views<span class="op">::</span>all<span class="op">(</span>v<span class="op">))</span>;</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> _ <span class="op">:</span> state<span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> i <span class="op">:</span> av<span class="op">)</span> <span class="op">{</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>      benchmark<span class="op">::</span>DoNotOptimize<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ex">Benchmark</span>                                           Time      Time vector   Time any_view</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ex">-----------------------------------------------------------------------------------------</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_vector</span> vs. BM_AnyView]/1024                  +7.3364              237            1975</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_vector</span> vs. BM_AnyView]/2048                  +7.7186              464            4042</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_vector</span> vs. BM_AnyView]/4096                  +7.7098              920            8011</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_vector</span> vs. BM_AnyView]/8192                  +7.6034             1835           15790</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_vector</span> vs. BM_AnyView]/16384                 +7.7470             3654           31966</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_vector</span> vs. BM_AnyView]/32768                 +8.1498             7300           66796</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_vector</span> vs. BM_AnyView]/65536                 +8.0808            14602          132599</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_vector</span> vs. BM_AnyView]/131072                +8.0281            29189          263523</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_vector</span> vs. BM_AnyView]/262144                +7.4773            58497          495899</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="ex">OVERALL_GEOMEAN</span>                                  +8.6630                0               0</span></code></pre></div>
<p>We can see that <code class="sourceCode cpp">any_view</code> is 8.6
times slower on iteration than
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>.
However, this benchmark is not a realistic use case. No one would create
a <code class="sourceCode cpp">vector</code>, immediately create a type
erased wrapper <code class="sourceCode cpp">any_view</code> that wraps
it and then iterate through it. Similarly, no one would create a lambda,
immediately create a <code class="sourceCode cpp">std<span class="op">::</span>function</code> and
then call it.</p>
<h3 data-number="7.12.2" id="a-slightly-more-realistic-benchmark-a-view-pipeline-vs-any_view"><span class="header-section-number">7.12.2</span> A slightly more realistic
benchmark: A view pipeline vs
<code class="sourceCode cpp">any_view</code><a href="#a-slightly-more-realistic-benchmark-a-view-pipeline-vs-any_view" class="self-link"></a></h3>
<p>Since <code class="sourceCode cpp">any_view</code> is intended to be
used at an ABI boundary, a more realistic benchmark would separate the
creation of the view in a different TU. Furthermore, most uses of
<code class="sourceCode cpp">any_view</code> are expected to be with
non-trivial view pipelines, not with e.g. a raw
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>.
As the pipeline increases in complexity, the relative cost of using
<code class="sourceCode cpp">any_view</code> becomes smaller and
smaller.</p>
<p>Let’s consider the following example, where we create a moderately
complex pipeline and pass it across an ABI boundary either with a
<code class="sourceCode cpp">any_view</code> or with the pipeline’s
actual type:</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="co">// header file</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Widget <span class="op">{</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string name;</span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> size;</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> UI <span class="op">{</span></span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>Widget<span class="op">&gt;</span> widgets_;</span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>ranges<span class="op">::</span>transform_view<span class="op">&lt;</span>complicated<span class="op">...&gt;</span> getWidgetNames<span class="op">()</span>;</span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a><span class="co">// cpp file</span></span>
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>ranges<span class="op">::</span>transform_view<span class="op">&lt;</span>complicated<span class="op">...&gt;</span> UI<span class="op">::</span>getWidgetNames<span class="op">()</span> <span class="op">{</span></span>
<span id="cb25-14"><a href="#cb25-14" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> widgets_ <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>filter<span class="op">([](</span><span class="kw">const</span> Widget<span class="op">&amp;</span> widget<span class="op">)</span> <span class="op">{</span></span>
<span id="cb25-15"><a href="#cb25-15" aria-hidden="true" tabindex="-1"></a>           <span class="cf">return</span> widget<span class="op">.</span>size <span class="op">&gt;</span> <span class="dv">10</span>;</span>
<span id="cb25-16"><a href="#cb25-16" aria-hidden="true" tabindex="-1"></a>         <span class="op">})</span> <span class="op">|</span></span>
<span id="cb25-17"><a href="#cb25-17" aria-hidden="true" tabindex="-1"></a>         std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">(&amp;</span>Widget<span class="op">::</span>name<span class="op">)</span>;</span>
<span id="cb25-18"><a href="#cb25-18" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And this is what we are going to measure:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>  lib<span class="op">::</span>UI ui <span class="op">=</span> <span class="op">{...}</span>;</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> _ <span class="op">:</span> state<span class="op">)</span> <span class="op">{</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span><span class="op">&amp;</span> name <span class="op">:</span> ui<span class="op">.</span>getWidgetNames<span class="op">())</span> <span class="op">{</span></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>      benchmark<span class="op">::</span>DoNotOptimize<span class="op">(</span>name<span class="op">)</span>;</span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span></code></pre></div>
<p>In the <code class="sourceCode cpp">any_view</code> case, we simply
replace <code class="sourceCode cpp">std<span class="op">::</span>ranges<span class="op">::</span>transform_view<span class="op">&lt;</span>complicated<span class="op">...&gt;</span></code>
by <code class="sourceCode cpp">std<span class="op">::</span>ranges<span class="op">::</span>any_view</code>
and we measure the same thing.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">Benchmark</span>                                                 Time    Time complicated      Time any_view</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ex">-----------------------------------------------------------------------------------------------------</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_RawPipeline</span> vs. BM_AnyViewPipeline]/1024           +0.8536                1315               2438</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_RawPipeline</span> vs. BM_AnyViewPipeline]/2048           +0.8162                2713               4928</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_RawPipeline</span> vs. BM_AnyViewPipeline]/4096           +0.6976                5637               9570</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_RawPipeline</span> vs. BM_AnyViewPipeline]/8192           +0.7154               11539              19795</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_RawPipeline</span> vs. BM_AnyViewPipeline]/16384          +0.6611               23475              38994</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_RawPipeline</span> vs. BM_AnyViewPipeline]/32768          +0.6379               47792              78278</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_RawPipeline</span> vs. BM_AnyViewPipeline]/65536          +0.6174               96976             156851</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_RawPipeline</span> vs. BM_AnyViewPipeline]/131072         +0.6087              197407             317560</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_RawPipeline</span> vs. BM_AnyViewPipeline]/262144         +0.5882              399623             634694</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="ex">OVERALL_GEOMEAN</span>                                        +0.6862                   0                  0</span></code></pre></div>
<p>This benchmark shows that
<code class="sourceCode cpp">any_view</code> is about 68% slower on
iteration, which is much better than the previous naive benchmark.
However, note that this benchmark is still not very realistic. Writing
down the type of the view pipeline causes an implementation detail (how
the pipeline is implemented) to leak into the API and the ABI of this
class, and increases header dependencies, which defeats the purpose of
hiding implementation into a separate translation unit.</p>
<p>As a result, most people would instead copy the results of the
pipeline into a container and return that from <code class="sourceCode cpp">getWidgetNames<span class="op">()</span></code>,
for example as a <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span></code>.
This leads us to our last benchmark, which we believe is much more
representative of what people would do in the wild.</p>
<h3 data-number="7.12.3" id="a-realistic-benchmark-a-copy-of-vectorstring-vs-any_view"><span class="header-section-number">7.12.3</span> A realistic benchmark: A
copy of <code class="sourceCode cpp">vector<span class="op">&lt;</span>string<span class="op">&gt;</span></code>
vs <code class="sourceCode cpp">any_view</code><a href="#a-realistic-benchmark-a-copy-of-vectorstring-vs-any_view" class="self-link"></a></h3>
<p>As mentioned above, various concerns that are not related to
performance like readability or API/ABI stability mean that the previous
benchmarks are not really representative of what happens in the real
world. Instead, people in the wild tend to use owning containers like
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
as a type erasure tool for lack of a better tool. Such code would look
like this:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="co">// header file</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> UI <span class="op">{</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>Widget<span class="op">&gt;</span> widgets_;</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span> getWidgetNames<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-7"><a href="#cb27-7" aria-hidden="true" tabindex="-1"></a><span class="co">// cpp file</span></span>
<span id="cb27-8"><a href="#cb27-8" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span> UI<span class="op">::</span>getWidgetNames<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb27-9"><a href="#cb27-9" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span> results;</span>
<span id="cb27-10"><a href="#cb27-10" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">const</span> Widget<span class="op">&amp;</span> widget <span class="op">:</span> widgets_<span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-11"><a href="#cb27-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>widget<span class="op">.</span>size <span class="op">&gt;</span> <span class="dv">10</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb27-12"><a href="#cb27-12" aria-hidden="true" tabindex="-1"></a>      results<span class="op">.</span>push_back<span class="op">(</span>widget<span class="op">.</span>name<span class="op">)</span>;</span>
<span id="cb27-13"><a href="#cb27-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb27-14"><a href="#cb27-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb27-15"><a href="#cb27-15" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> results;</span>
<span id="cb27-16"><a href="#cb27-16" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb3"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">Benchmark</span>                                                       Time      Time vector Time any_view</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ex">---------------------------------------------------------------------------------------------------</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_VectorCopy</span> vs. BM_AnyViewPipeline]/1024                  <span class="at">-0.7042</span>             8243          2438</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_VectorCopy</span> vs. BM_AnyViewPipeline]/2048                  <span class="at">-0.7226</span>            17764          4928</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_VectorCopy</span> vs. BM_AnyViewPipeline]/4096                  <span class="at">-0.7379</span>            36516          9570</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_VectorCopy</span> vs. BM_AnyViewPipeline]/8192                  <span class="at">-0.7927</span>            95467         19795</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_VectorCopy</span> vs. BM_AnyViewPipeline]/16384                 <span class="at">-0.7893</span>           185104         38994</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_VectorCopy</span> vs. BM_AnyViewPipeline]/32768                 <span class="at">-0.7890</span>           371035         78278</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_VectorCopy</span> vs. BM_AnyViewPipeline]/65536                 <span class="at">-0.8079</span>           816621        156851</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_VectorCopy</span> vs. BM_AnyViewPipeline]/131072                <span class="at">-0.8121</span>          1690305        317560</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_VectorCopy</span> vs. BM_AnyViewPipeline]/262144                <span class="at">-0.8228</span>          3581632        634694</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a><span class="ex">OVERALL_GEOMEAN</span>                                              <span class="at">-0.7723</span>                0             0</span></code></pre></div>
<p>With this more realistic use case, we can see that
<code class="sourceCode cpp">any_view</code> is 3 times faster. For the
returning <code class="sourceCode cpp">vector</code> case, we have some
variations of the implementations to produce the vector, including
<code class="sourceCode cpp">reserve</code> the maximum possible size,
or use the range pipelines with
<code class="sourceCode cpp">ranges<span class="op">::</span>to</code>.
They all have extremely similar results. In our benchmark, 10% of the
<code class="sourceCode cpp">Widget</code>s were filtered out by the
filter pipeline and the <code class="sourceCode cpp">name</code>
string’s length is randomly 0-30. So some of
<code class="sourceCode cpp">string</code>s are in the SBO and some are
allocated on the heap. We maintain that this code pattern is very common
in the wild: making the code simple and clean at the cost of copying
data, even though most of the callers don’t actually need a copy of the
data at all.</p>
<p>In conclusion, we believe that while it’s easy to craft benchmarks
that make <code class="sourceCode cpp">any_view</code> look bad
performance-wise, in reality this type can often lead to better
performance by sidestepping the need to own the data being iterated
over.</p>
<p>Furthermore, by putting this type in the Standard library, we would
make it possible for implementers to use optimizations like selective
devirtualization of some common operations like
<code class="sourceCode cpp">for_each</code> to achieve large
performance gains in specific cases.</p>
<h3 data-number="7.12.4" id="another-common-use-case-function-arguments-vector-vs-any_view"><span class="header-section-number">7.12.4</span> Another Common Use Case:
Function Arguments <code class="sourceCode cpp">vector</code> vs
<code class="sourceCode cpp">any_view</code><a href="#another-common-use-case-function-arguments-vector-vs-any_view" class="self-link"></a></h3>
<p>Another very common use case is that library authors provide an API
that takes a range of elements. The library authors would like to hide
implementation details in its own library to reduce the header
dependencies and avoid leaking implementation details. Due to the lack
of type erasure utilities, typically the API takes a
<code class="sourceCode cpp">vector</code>, even though the
implementation only needs to iterate once over the elements.</p>
<p>This is the benchmark we are measuring.</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="co">// algo.hpp</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> algo1<span class="op">(</span><span class="kw">const</span> std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;&amp;</span> strings<span class="op">)</span>;</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> algo2<span class="op">(</span>std<span class="op">::</span>ranges<span class="op">::</span>any_view<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span> strings<span class="op">)</span>;</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a><span class="co">// algo.cpp</span></span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> algo1<span class="op">(</span><span class="kw">const</span> std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;&amp;</span> strings<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> result <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> str <span class="op">:</span> strings<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>str<span class="op">.</span>size<span class="op">()</span> <span class="op">&gt;</span> <span class="dv">6</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>      result <span class="op">+=</span> str<span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> result;</span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-16"><a href="#cb28-16" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> algo2<span class="op">(</span>std<span class="op">::</span>ranges<span class="op">::</span>any_view<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span> strings<span class="op">)</span></span>
<span id="cb28-17"><a href="#cb28-17" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb28-18"><a href="#cb28-18" aria-hidden="true" tabindex="-1"></a>  <span class="dt">int</span> result <span class="op">=</span> <span class="dv">0</span>;</span>
<span id="cb28-19"><a href="#cb28-19" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> str <span class="op">:</span> strings<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-20"><a href="#cb28-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>str<span class="op">.</span>size<span class="op">()</span> <span class="op">&gt;</span> <span class="dv">6</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-21"><a href="#cb28-21" aria-hidden="true" tabindex="-1"></a>      result <span class="op">+=</span> str<span class="op">.</span>size<span class="op">()</span>;</span>
<span id="cb28-22"><a href="#cb28-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb28-23"><a href="#cb28-23" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb28-24"><a href="#cb28-24" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> result;</span>
<span id="cb28-25"><a href="#cb28-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>With the <code class="sourceCode cpp">vector</code> version, the user
needs to create a temporary <code class="sourceCode cpp">vector</code>
if they do not have it at the first place. So in our benchmark, we are
measuring</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> _ <span class="op">:</span> state<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span> widget_names;</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a>  widget_names<span class="op">.</span>reserve<span class="op">(</span>ui<span class="op">.</span>widgets_<span class="op">.</span>size<span class="op">())</span>;</span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span> <span class="op">(</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> widget <span class="op">:</span> ui<span class="op">.</span>widgets_<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a>    widget_names<span class="op">.</span>push_back<span class="op">(</span>widget<span class="op">.</span>name<span class="op">)</span>;</span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> res <span class="op">=</span> lib<span class="op">::</span>algo1<span class="op">(</span>widget_names<span class="op">)</span>;</span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>  benchmark<span class="op">::</span>DoNotOptimize<span class="op">(</span>res<span class="op">)</span>;</span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>With the <code class="sourceCode cpp">any_view</code>, we can simply
pass in a <code class="sourceCode cpp">transform_view</code></p>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> _ <span class="op">:</span> state<span class="op">)</span> <span class="op">{</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> res <span class="op">=</span> lib<span class="op">::</span>algo2<span class="op">(</span>ui<span class="op">.</span>widgets_ <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">(&amp;</span>Widget<span class="op">::</span>name<span class="op">))</span>;</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>  benchmark<span class="op">::</span>DoNotOptimize<span class="op">(</span>res<span class="op">)</span>;</span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>And here is the result:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">Benchmark</span>                                                     Time   Time vector Time any_view</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="ex">----------------------------------------------------------------------------------------------</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_algo_vector</span> vs. BM_algo_AnyView]/1024                  <span class="at">-0.8098</span>          9615          1829</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_algo_vector</span> vs. BM_algo_AnyView]/2048                  <span class="at">-0.8169</span>         20651          3782</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_algo_vector</span> vs. BM_algo_AnyView]/4096                  <span class="at">-0.8188</span>         41035          7436</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_algo_vector</span> vs. BM_algo_AnyView]/8192                  <span class="at">-0.8275</span>         87227         15044</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_algo_vector</span> vs. BM_algo_AnyView]/16384                 <span class="at">-0.8315</span>        182922         30818</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_algo_vector</span> vs. BM_algo_AnyView]/32768                 <span class="at">-0.8407</span>        381383         60771</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_algo_vector</span> vs. BM_algo_AnyView]/65536                 <span class="at">-0.8425</span>        793920        125004</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_algo_vector</span> vs. BM_algo_AnyView]/131072                <span class="at">-0.8656</span>       1733654        232982</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="ex">[BM_algo_vector</span> vs. BM_algo_AnyView]/262144                <span class="at">-0.8640</span>       3592842        488714</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a><span class="ex">OVERALL_GEOMEAN</span>                                            <span class="at">-0.8364</span>             0             0</span></code></pre></div>
<p>We can see the <code class="sourceCode cpp">any_view</code> version
is 4 times faster. This is a very common pattern in the real world code.
<code class="sourceCode cpp">vector</code> has been used in API
boundaries as a type-erasure tool.</p>
<h1 data-number="8" id="implementation-experience"><span class="header-section-number">8</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h1>
<p><code class="sourceCode cpp">any_view</code> has been implemented in
<span class="citation" data-cites="rangev3">[<a href="https://github.com/ericniebler/range-v3" role="doc-biblioref">range-v3</a>]</span>, with equivalent semantics as
proposed here. The authors also implemented a version that directly
follows the proposed wording below without any issue <span class="citation" data-cites="ours">[<a href="https://github.com/huixie90/cpp_papers/tree/main/impl/any_view" role="doc-biblioref">ours</a>]</span> and <span class="citation" data-cites="bemanproject">[<a href="https://github.com/bemanproject/any_view" role="doc-biblioref">beman-project</a>]</span>.</p>
<h1 data-number="9" id="wording"><span class="header-section-number">9</span> Wording<a href="#wording" class="self-link"></a></h1>
<h2 data-number="9.1" id="addition-to-ranges"><span class="header-section-number">9.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://wg21.link/ranges.syn">[ranges.syn]</a></span>, header
<code class="sourceCode cpp">ranges</code> synopsis:</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="co">// [...]</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [...]</span></span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [range.any], any view</span></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">enum</span> <span class="kw">class</span> any_view_options</span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>      input <span class="op">=</span> <span class="dv">1</span>,</span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a>      forward <span class="op">=</span> <span class="dv">3</span>,</span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a>      bidirectional <span class="op">=</span> <span class="dv">7</span>,</span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a>      random_access <span class="op">=</span> <span class="dv">15</span>,</span>
<span id="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a>      contiguous <span class="op">=</span> <span class="dv">31</span>,</span>
<span id="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a>      sized <span class="op">=</span> <span class="dv">32</span>,</span>
<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a>      borrowed <span class="op">=</span> <span class="dv">64</span>,</span>
<span id="cb31-15"><a href="#cb31-15" aria-hidden="true" tabindex="-1"></a>      copyable <span class="op">=</span> <span class="dv">128</span></span>
<span id="cb31-16"><a href="#cb31-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb31-17"><a href="#cb31-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-18"><a href="#cb31-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> any_view_options <span class="kw">operator</span><span class="op">|(</span>any_view_options, any_view_options<span class="op">)</span> <span class="kw">noexcept</span>;</span>
<span id="cb31-19"><a href="#cb31-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> any_view_options <span class="kw">operator</span><span class="op">&amp;(</span>any_view_options, any_view_options<span class="op">)</span> <span class="kw">noexcept</span>;</span>
<span id="cb31-20"><a href="#cb31-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-21"><a href="#cb31-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> <em>flag-is-set</em><span class="op">(</span>any_view_options opts, any_view_options flag<span class="op">)</span>; <span class="co">// exposition-only</span></span>
<span id="cb31-22"><a href="#cb31-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-23"><a href="#cb31-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb31-24"><a href="#cb31-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <em>rvalue-ref-t</em> <span class="op">=</span> <em>see below</em>; <span class="co">// exposition-only</span></span>
<span id="cb31-25"><a href="#cb31-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-26"><a href="#cb31-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Element,</span>
<span id="cb31-27"><a href="#cb31-27" aria-hidden="true" tabindex="-1"></a>            any_view_options Opts <span class="op">=</span> any_view_options<span class="op">::</span>input,</span>
<span id="cb31-28"><a href="#cb31-28" aria-hidden="true" tabindex="-1"></a>            <span class="kw">class</span> Ref <span class="op">=</span> Element<span class="op">&amp;</span>,</span>
<span id="cb31-29"><a href="#cb31-29" aria-hidden="true" tabindex="-1"></a>            <span class="kw">class</span> RValueRef <span class="op">=</span> <em>rvalue-ref-t</em><span class="op">&lt;</span>Ref<span class="op">&gt;</span>,</span>
<span id="cb31-30"><a href="#cb31-30" aria-hidden="true" tabindex="-1"></a>            <span class="kw">class</span> Diff <span class="op">=</span> <span class="dt">ptrdiff_t</span><span class="op">&gt;</span></span>
<span id="cb31-31"><a href="#cb31-31" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> any_view;</span>
<span id="cb31-32"><a href="#cb31-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-33"><a href="#cb31-33" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Element, any_view_options Opts, <span class="kw">class</span> Ref, <span class="kw">class</span> RValueRef,</span>
<span id="cb31-34"><a href="#cb31-34" aria-hidden="true" tabindex="-1"></a>            <span class="kw">class</span> Diff<span class="op">&gt;</span></span>
<span id="cb31-35"><a href="#cb31-35" aria-hidden="true" tabindex="-1"></a>  <span class="kw">inline</span> <span class="kw">constexpr</span> <span class="dt">bool</span></span>
<span id="cb31-36"><a href="#cb31-36" aria-hidden="true" tabindex="-1"></a>      enable_borrowed_range<span class="op">&lt;</span>any_view<span class="op">&lt;</span>Element, Opts, Ref, RValueRef, Diff<span class="op">&gt;&gt;</span> <span class="op">=</span></span>
<span id="cb31-37"><a href="#cb31-37" aria-hidden="true" tabindex="-1"></a>          <span class="op">(</span>Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>borrowed<span class="op">)</span> <span class="op">==</span> any_view_options<span class="op">::</span>borrowed;</span>
<span id="cb31-38"><a href="#cb31-38" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="9.2" id="any_view"><span class="header-section-number">9.2</span>
<code class="sourceCode cpp">any_view</code><a href="#any_view" class="self-link"></a></h2>
<p>Add the following subclause to <span>25.5
<a href="https://wg21.link/range.utility">[range.utility]</a></span></p>
<h3 class="unnumbered" id="any-view-range.any">?.?.? Any view
[range.any]<a href="#any-view-range.any" class="self-link"></a></h3>
<h4 class="unnumbered" id="definition-range.any.def">?.?.?.1 Definition
[range.any.def]<a href="#definition-range.any.def" class="self-link"></a></h4>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
The following definitions apply to this Clause:</p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
A <em>view object</em> is an object of a type that models the
<code class="sourceCode cpp">ranges<span class="op">::</span>view</code>
(<span>25.4.4
<a href="https://wg21.link/range.view">[range.view]</a></span>)
concept.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
A <em>view wrapper type</em> is a type that holds a <em>view object</em>
and supports <code class="sourceCode cpp">ranges<span class="op">::</span>begin</code> and
<code class="sourceCode cpp">ranges<span class="op">::</span>end</code>
operations that forward to that object.</p>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
A <em>target view object</em> is the <em>view object</em> held by an
object of a <em>view wrapper type</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
An <em>iterator object</em> is an object of a type that models the
<code class="sourceCode cpp">input_iterator</code> (<span>24.3.4.9
<a href="https://wg21.link/iterator.concept.input">[iterator.concept.input]</a></span>)
concept.</p>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
An <em>iterator wrapper type</em> is a type that holds an <em>iterator
object</em> and forward operations to that object.</p>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
A <em>target iterator object</em> is the <em>iterator object</em> held
by an object of a <em>iterator wrapper type</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
A <em>sentinel object</em> is an object of a type that models <code class="sourceCode cpp">sentinel_for<span class="op">&lt;</span>Iter<span class="op">&gt;</span></code>
(<span>24.3.4.7
<a href="https://wg21.link/iterator.concept.sentinel">[iterator.concept.sentinel]</a></span>)
concept for some <code class="sourceCode cpp">Iter</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
A <em>sentinel wrapper type</em> is a type that holds an <em>sentinel
object</em> and forwards operations to that object.</p>
<p><span class="marginalizedparent"><a class="marginalized">10</a></span> A
<em>target sentinel object</em> is the <em>sentinel object</em> held by
an object of a <em>sentinel wrapper type</em>.</p>
<h4 class="unnumbered" id="general-range.any.general">?.?.?.2 General
[range.any.general]<a href="#general-range.any.general" class="self-link"></a></h4>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
The <code class="sourceCode cpp">any_view</code> class template provides
polymorphic wrappers that generalize the notion of a <em>view
object</em>. These wrappers can store, move, and traverse arbitrary
<em>view object</em>s, given a view element type and a view
category.</p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
Recommended practice: Implementations should avoid the use of
dynamically allocated memory for a small contained <em>target view
object</em> of type <code class="sourceCode cpp">T</code> which
satisfies <code class="sourceCode cpp">is_nothrow_move_constructible_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>.</p>
<h4 class="unnumbered" id="class-template-any_view-range.any.class">?.?.?.3 Class template
<code class="sourceCode cpp">any_view</code> [range.any.class]<a href="#class-template-any_view-range.any.class" class="self-link"></a></h4>
<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Element,</span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>          any_view_options Opts <span class="op">=</span> any_view_options<span class="op">::</span>input,</span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> Ref <span class="op">=</span> Element<span class="op">&amp;</span>,</span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> RValueRef <span class="op">=</span> <em>rvalue-ref-t</em><span class="op">&lt;</span>Ref<span class="op">&gt;</span>,</span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>          <span class="kw">class</span> Diff <span class="op">=</span> <span class="dt">ptrdiff_t</span><span class="op">&gt;</span></span>
<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> any_view <span class="op">{</span></span>
<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> <em>iterator</em>; <span class="co">// exposition-only</span></span>
<span id="cb32-8"><a href="#cb32-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> <em>sentinel</em>; <span class="co">// exposition-only</span></span>
<span id="cb32-9"><a href="#cb32-9" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb32-10"><a href="#cb32-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [range.any.ctor], constructors, assignment, and destructor</span></span>
<span id="cb32-11"><a href="#cb32-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Rng<span class="op">&gt;</span> <span class="kw">constexpr</span> any_view<span class="op">(</span>Rng<span class="op">&amp;&amp;</span> rng<span class="op">)</span>;</span>
<span id="cb32-12"><a href="#cb32-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> any_view<span class="op">(</span><span class="kw">const</span> any_view<span class="op">&amp;)</span>;</span>
<span id="cb32-13"><a href="#cb32-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> any_view<span class="op">(</span>any_view<span class="op">&amp;&amp;)</span> <span class="kw">noexcept</span>;</span>
<span id="cb32-14"><a href="#cb32-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-15"><a href="#cb32-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> any_view <span class="op">&amp;</span><span class="kw">operator</span><span class="op">=(</span><span class="kw">const</span> any_view<span class="op">&amp;)</span></span>
<span id="cb32-16"><a href="#cb32-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> any_view <span class="op">&amp;</span><span class="kw">operator</span><span class="op">=(</span>any_view<span class="op">&amp;&amp;)</span> <span class="kw">noexcept</span>;</span>
<span id="cb32-17"><a href="#cb32-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-18"><a href="#cb32-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="op">~</span>any_view<span class="op">()</span>;</span>
<span id="cb32-19"><a href="#cb32-19" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-20"><a href="#cb32-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [range.any.access], range access</span></span>
<span id="cb32-21"><a href="#cb32-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <em>iterator</em> begin<span class="op">()</span>;</span>
<span id="cb32-22"><a href="#cb32-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <em>sentinel</em> end<span class="op">()</span>;</span>
<span id="cb32-23"><a href="#cb32-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-24"><a href="#cb32-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <em>make-unsigned-like-t</em><span class="op">&lt;</span>Diff<span class="op">&gt;</span> size<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb32-25"><a href="#cb32-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb32-26"><a href="#cb32-26" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [range.any.swap], swap</span></span>
<span id="cb32-27"><a href="#cb32-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">void</span> swap<span class="op">(</span>any_view<span class="op">&amp;)</span> <span class="kw">noexcept</span>;</span>
<span id="cb32-28"><a href="#cb32-28" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">friend</span> <span class="dt">void</span> swap<span class="op">(</span>any_view<span class="op">&amp;</span>, any_view<span class="op">&amp;)</span> <span class="kw">noexcept</span>;</span>
<span id="cb32-29"><a href="#cb32-29" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
The exposition-only
<code class="sourceCode cpp"><em>rvalue-ref-t</em></code> is equivalent
to:</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <em>rvalue-ref</em> <span class="op">{</span> <span class="co">// exposition-only</span></span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> type <span class="op">=</span> T;</span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <em>rvalue-ref</em><span class="op">&lt;</span>T<span class="op">&amp;&gt;</span> <span class="op">{</span></span>
<span id="cb33-8"><a href="#cb33-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> type <span class="op">=</span> T<span class="op">&amp;&amp;</span>;</span>
<span id="cb33-9"><a href="#cb33-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb33-10"><a href="#cb33-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-11"><a href="#cb33-11" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb33-12"><a href="#cb33-12" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> <em>rvalue-ref-t</em> <span class="op">=</span> <span class="kw">typename</span> <em>rvalue-ref</em><span class="op">&lt;</span>T<span class="op">&gt;::</span>type;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb34"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> any_view_options <span class="kw">operator</span><span class="op">|(</span>any_view_options lhs, any_view_options rhs<span class="op">)</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> any_view_options<span class="op">(</span>to_underlying<span class="op">(</span>lhs<span class="op">)</span> <span class="op">|</span> to_underlying<span class="op">(</span>rhs<span class="op">))</span>;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb36"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> any_view_options <span class="kw">operator</span><span class="op">&amp;(</span>any_view_options, any_view_options<span class="op">)</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> any_view_options<span class="op">(</span>to_underlying<span class="op">(</span>lhs<span class="op">)</span> <span class="op">&amp;</span> to_underlying<span class="op">(</span>rhs<span class="op">))</span>;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb38"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">bool</span> <em>flag-is-set</em><span class="op">(</span>any_view_options opts, any_view_options flag<span class="op">)</span>; <span class="co">// exposition-only</span></span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a>  <span class="cf">return</span> <span class="op">(</span>opts <span class="op">&amp;</span> flag<span class="op">)</span> <span class="op">!=</span> any_view_options<span class="op">(</span><span class="dv">0</span><span class="op">)</span>;</span></code></pre></div>
</div>
<h4 class="unnumbered" id="constructors-assignment-and-destructor-range.any.ctor">?.?.?.4
Constructors, assignment, and destructor [range.any.ctor]<a href="#constructors-assignment-and-destructor-range.any.ctor" class="self-link"></a></h4>
<div class="sourceCode" id="cb40"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Rng<span class="op">&gt;</span> <span class="kw">constexpr</span> any_view<span class="op">(</span>Rng<span class="op">&amp;&amp;</span> rng<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<em>Constraints</em>:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.1)</a></span>
<code class="sourceCode cpp">remove_cvref_t<span class="op">&lt;</span>Rng<span class="op">&gt;</span></code>
is not the same type as <code class="sourceCode cpp">any_view</code>,
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.2)</a></span>
<code class="sourceCode cpp">Rng</code> models
<code class="sourceCode cpp">viewable_range</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.3)</a></span>
either <code class="sourceCode cpp"><em>flag-is-set</em><span class="op">(</span>Opts, any_view_options<span class="op">::</span>sized<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code>, or
<code class="sourceCode cpp">Rng</code> models
<code class="sourceCode cpp">sized_range</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.4)</a></span>
either <code class="sourceCode cpp"><em>flag-is-set</em><span class="op">(</span>Opts, any_view_options<span class="op">::</span>borrowed<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code>, or
<code class="sourceCode cpp">Rng</code> models
<code class="sourceCode cpp">borrowed_range</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.5)</a></span>
either <code class="sourceCode cpp"><em>flag-is-set</em><span class="op">(</span>Opts, any_view_options<span class="op">::</span>copyable<span class="op">)</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code>, or
<code class="sourceCode cpp">all_t<span class="op">&lt;</span>Rng<span class="op">&gt;</span></code>
models <code class="sourceCode cpp">copyable</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.6)</a></span>
<code class="sourceCode cpp">is_convertible_v<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>all_t<span class="op">&lt;</span>Rng<span class="op">&gt;&gt;</span>, Ref<span class="op">&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.7)</a></span>
<code class="sourceCode cpp">is_convertible_v<span class="op">&lt;</span>range_value_t<span class="op">&lt;</span>all_t<span class="op">&lt;</span>Rng<span class="op">&gt;&gt;</span>, remove_cv_t<span class="op">&lt;</span>Element<span class="op">&gt;&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.8)</a></span>
<code class="sourceCode cpp">is_convertible_v<span class="op">&lt;</span>range_rvalue_reference_t<span class="op">&lt;</span>all_t<span class="op">&lt;</span>Rng<span class="op">&gt;&gt;</span>, RValueRef<span class="op">&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.9)</a></span>
<code class="sourceCode cpp">is_convertible_v<span class="op">&lt;</span>range_difference_t<span class="op">&lt;</span>all_t<span class="op">&lt;</span>Rng<span class="op">&gt;&gt;</span>, Diff<span class="op">&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.10)</a></span> Let
<code class="sourceCode cpp">CAT</code> be <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>contiguous</code>,
<code class="sourceCode cpp">R</code> be <code class="sourceCode cpp">all_t<span class="op">&lt;</span>Rng<span class="op">&gt;</span></code>,</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.10.1)</a></span>
If <code class="sourceCode cpp">CAT</code> is <code class="sourceCode cpp">any_views_options<span class="op">::</span>contiguous</code>,
<code class="sourceCode cpp">R</code> models
<code class="sourceCode cpp">contiguous_range</code></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.10.2)</a></span>
Otherwise, if <code class="sourceCode cpp">CAT</code> is <code class="sourceCode cpp">any_views_options<span class="op">::</span>random_access</code>,
<code class="sourceCode cpp">R</code> models
<code class="sourceCode cpp">random_access_range</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.10.3)</a></span>
Otherwise, if <code class="sourceCode cpp">CAT</code> is <code class="sourceCode cpp">any_views_options<span class="op">::</span>bidirectional</code>,
<code class="sourceCode cpp">R</code> models
<code class="sourceCode cpp">bidirectional_range</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.10.4)</a></span>
Otherwise if <code class="sourceCode cpp">CAT</code> is <code class="sourceCode cpp">any_views_options<span class="op">::</span>forward</code>,
<code class="sourceCode cpp">R</code> models
<code class="sourceCode cpp">forward_range</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.10.5)</a></span>
Otherwise, <code class="sourceCode cpp">CAT</code> is <code class="sourceCode cpp">any_views_options<span class="op">::</span>input</code>,
and <code class="sourceCode cpp">R</code> models
<code class="sourceCode cpp">input_range</code></p></li>
</ul></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>Postconditions</em>:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.1)</a></span>
<code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has no <em>target view object</em> if <code class="sourceCode cpp">remove_cvref_t<span class="op">&lt;</span>Rng<span class="op">&gt;</span></code>
is a specialization of the <code class="sourceCode cpp">any_view</code>
class template, and <code class="sourceCode cpp">rng</code> has no
<em>target view object</em>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.2)</a></span>
Otherwise, <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has a <em>target view object</em> of type <code class="sourceCode cpp">all_t<span class="op">&lt;</span>Rng<span class="op">&gt;</span></code>
direct-non-list-initialized with <code class="sourceCode cpp">std​<span class="op">::</span>​forward<span class="op">&lt;</span>Rng<span class="op">&gt;(</span>rng<span class="op">)</span></code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>Throws</em>: Any exception thrown by the initialization of the
<em>target view object</em>. May throw
<code class="sourceCode cpp">bad_alloc</code>.</p>
</div>
<div class="sourceCode" id="cb41"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> any_view<span class="op">(</span><span class="kw">const</span> any_view<span class="op">&amp;</span> other<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<em>Constraints</em>: <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>copyable</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>copyable</code></p>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
<em>Postconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has no <em>target view object</em> if
<code class="sourceCode cpp">other</code> had no <em>target view
object</em>. Otherwise, the <em>target view object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
is a copy of the <em>target view object</em> of
<code class="sourceCode cpp">other</code>.</p>
</div>
<div class="sourceCode" id="cb42"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> any_view<span class="op">(</span>any_view<span class="op">&amp;&amp;</span> other<span class="op">)</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
<em>Postconditions</em>: The <em>target view object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
is the <em>target view object</em>
<code class="sourceCode cpp">other</code> had before construction, and
<code class="sourceCode cpp">other</code> is in a valid state with an
unspecified value.</p>
</div>
<div class="sourceCode" id="cb43"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> any_view <span class="op">&amp;</span><span class="kw">operator</span><span class="op">=(</span><span class="kw">const</span> any_view<span class="op">&amp;</span> other<span class="op">)</span></span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<em>Constraints</em>: <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>copyable</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>copyable</code></p>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp">any_view<span class="op">(</span>other<span class="op">).</span>swap<span class="op">(*</span><span class="kw">this</span><span class="op">)</span>;</code></p>
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
<em>Returns</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>.</p>
</div>
<div class="sourceCode" id="cb44"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> any_view <span class="op">&amp;</span><span class="kw">operator</span><span class="op">=(</span>any_view<span class="op">&amp;&amp;</span> other<span class="op">)</span></span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">10</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp">any_view<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>other<span class="op">)).</span>swap<span class="op">(*</span><span class="kw">this</span><span class="op">)</span>;</code></p>
<p><span class="marginalizedparent"><a class="marginalized">11</a></span>
<em>Returns</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>.</p>
</div>
<div class="sourceCode" id="cb45"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="op">~</span>any_view<span class="op">()</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">12</a></span>
<em>Effects</em>: Destroys the <em>target view object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>,
if any.</p>
</div>
<h4 class="unnumbered" id="range-access-range.any.access">?.?.?.5 Range
access [range.any.access]<a href="#range-access-range.any.access" class="self-link"></a></h4>
<div class="sourceCode" id="cb46"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <em>iterator</em> begin<span class="op">()</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<em>Preconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has a <em>target view object</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>Effects</em>: Let <code class="sourceCode cpp">v</code> be an lvalue
designating the <em>target view object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>,
returns an object of <em>iterator wrapper type</em>
<code class="sourceCode cpp"><em>iterator</em></code>, which holds a
<em>target iterator object</em> of <code class="sourceCode cpp">ranges<span class="op">::</span>begin<span class="op">(</span>v<span class="op">)</span></code></p>
</div>
<div class="sourceCode" id="cb47"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <em>sentinel</em> end<span class="op">()</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>Preconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has a <em>target view object</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<em>Effects</em>: Let <code class="sourceCode cpp">v</code> be an lvalue
designating the <em>target view object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>,
returns an object of <em>sentinel wrapper type</em>
<code class="sourceCode cpp"><em>sentinel</em></code>, which holds a
<em>target sentinel object</em> of <code class="sourceCode cpp">ranges<span class="op">::</span>end<span class="op">(</span>v<span class="op">)</span></code></p>
</div>
<div class="sourceCode" id="cb48"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <em>make-unsigned-like-t</em><span class="op">&lt;</span>Diff<span class="op">&gt;</span> size<span class="op">()</span> <span class="kw">const</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
<em>Constraints</em>: <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>sized</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>sized</code></p>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
<em>Preconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has a <em>target view object</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb49"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <em>make-unsigned-like-t</em><span class="op">&lt;</span>Diff<span class="op">&gt;(</span>ranges<span class="op">::</span>size<span class="op">(</span>v<span class="op">))</span>;</span></code></pre></div>
<p>where <code class="sourceCode cpp">v</code> is an lvalue designating
the <em>target view object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code></p>
</div>
<h4 class="unnumbered" id="swap-range.any.swap">?.?.?.6 Swap
[range.any.swap]<a href="#swap-range.any.swap" class="self-link"></a></h4>
<div class="sourceCode" id="cb50"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">void</span> swap<span class="op">(</span>any_view<span class="op">&amp;</span> other<span class="op">)</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<em>Effects</em>: Exchanges the <em>target view object</em>s of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
and <code class="sourceCode cpp">other</code></p>
</div>
<div class="sourceCode" id="cb51"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">friend</span> <span class="dt">void</span> swap<span class="op">(</span>any_view<span class="op">&amp;</span> lhs, any_view<span class="op">&amp;</span> rhs<span class="op">)</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp">lhs<span class="op">.</span>swap<span class="op">(</span>rhs<span class="op">)</span></code></p>
</div>
<h4 class="unnumbered" id="class-any_viewiterator-range.any.iterator">?.?.?.7 Class
any_view::iterator [range.any.iterator]<a href="#class-any_viewiterator-range.any.iterator" class="self-link"></a></h4>
<div class="sourceCode" id="cb52"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Element,</span>
<span id="cb52-3"><a href="#cb52-3" aria-hidden="true" tabindex="-1"></a>            any_view_options Opts <span class="op">=</span> any_view_options<span class="op">::</span>input,</span>
<span id="cb52-4"><a href="#cb52-4" aria-hidden="true" tabindex="-1"></a>            <span class="kw">class</span> Ref <span class="op">=</span> Element<span class="op">&amp;</span>,</span>
<span id="cb52-5"><a href="#cb52-5" aria-hidden="true" tabindex="-1"></a>            <span class="kw">class</span> RValueRef <span class="op">=</span> <em>rvalue-ref-t</em><span class="op">&lt;</span>Ref<span class="op">&gt;</span>,</span>
<span id="cb52-6"><a href="#cb52-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">class</span> Diff <span class="op">=</span> <span class="dt">ptrdiff_t</span><span class="op">&gt;</span></span>
<span id="cb52-7"><a href="#cb52-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> any_view<span class="op">&lt;</span>Element, Opts, Ref, RValueRef, Diff<span class="op">&gt;::</span><em>iterator</em> <span class="op">{</span></span>
<span id="cb52-8"><a href="#cb52-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb52-9"><a href="#cb52-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator_concept  <span class="op">=</span> <em>see below</em>;</span>
<span id="cb52-10"><a href="#cb52-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator_category <span class="op">=</span> <em>see below</em>;                        <span class="co">// not always present</span></span>
<span id="cb52-11"><a href="#cb52-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> value_type        <span class="op">=</span> remove_cv_t<span class="op">&lt;</span>Element<span class="op">&gt;</span>;</span>
<span id="cb52-12"><a href="#cb52-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> difference_type   <span class="op">=</span> Diff;</span>
<span id="cb52-13"><a href="#cb52-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-14"><a href="#cb52-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>iterator</em><span class="op">()</span>;</span>
<span id="cb52-15"><a href="#cb52-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-16"><a href="#cb52-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> Ref <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span>;</span>
<span id="cb52-17"><a href="#cb52-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-18"><a href="#cb52-18" aria-hidden="true" tabindex="-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>
<span id="cb52-19"><a href="#cb52-19" aria-hidden="true" tabindex="-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>
<span id="cb52-20"><a href="#cb52-20" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span> <span class="kw">requires</span> <em>see below</em>;</span>
<span id="cb52-21"><a href="#cb52-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-22"><a href="#cb52-22" aria-hidden="true" tabindex="-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>
<span id="cb52-23"><a href="#cb52-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">--(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb52-24"><a href="#cb52-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-25"><a href="#cb52-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>iterator</em><span class="op">&amp;</span> <span class="kw">operator</span><span class="op">+=(</span>difference_type n<span class="op">)</span>;</span>
<span id="cb52-26"><a href="#cb52-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>iterator</em><span class="op">&amp;</span> <span class="kw">operator</span><span class="op">-=(</span>difference_type n<span class="op">)</span>;</span>
<span id="cb52-27"><a href="#cb52-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-28"><a href="#cb52-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> Ref <span class="kw">operator</span><span class="op">[](</span>difference_type n<span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb52-29"><a href="#cb52-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> add_pointer_t<span class="op">&lt;</span>Ref<span class="op">&gt;</span> <span class="kw">operator</span><span class="op">-&gt;()</span> <span class="kw">const</span>;</span>
<span id="cb52-30"><a href="#cb52-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-31"><a href="#cb52-31" aria-hidden="true" tabindex="-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>iterator</em><span class="op">&amp;</span> y<span class="op">)</span>;</span>
<span id="cb52-32"><a href="#cb52-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-33"><a href="#cb52-33" aria-hidden="true" tabindex="-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">&lt;(</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="cb52-34"><a href="#cb52-34" aria-hidden="true" tabindex="-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">&gt;(</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="cb52-35"><a href="#cb52-35" aria-hidden="true" tabindex="-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">&lt;=(</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="cb52-36"><a href="#cb52-36" aria-hidden="true" tabindex="-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">&gt;=(</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="cb52-37"><a href="#cb52-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-38"><a href="#cb52-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">+(</span><em>iterator</em> i, difference_type n<span class="op">)</span>;</span>
<span id="cb52-39"><a href="#cb52-39" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">+(</span>difference_type n, <em>iterator</em> i<span class="op">)</span>;</span>
<span id="cb52-40"><a href="#cb52-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-41"><a href="#cb52-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">-(</span><em>iterator</em> i, difference_type n<span class="op">)</span>;</span>
<span id="cb52-42"><a href="#cb52-42" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> difference_type <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>iterator</em><span class="op">&amp;</span> y<span class="op">)</span>;</span>
<span id="cb52-43"><a href="#cb52-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-44"><a href="#cb52-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> RValueRef iter_move<span class="op">(</span><span class="kw">const</span> <em>iterator</em> <span class="op">&amp;</span>iter<span class="op">)</span>;</span>
<span id="cb52-45"><a href="#cb52-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb52-46"><a href="#cb52-46" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb52-47"><a href="#cb52-47" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<code class="sourceCode cpp"><em>iterator</em><span class="op">::</span>iterator_concept</code>
is defined as follows:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.1)</a></span> If
<code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>contiguous</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>contiguous</code>,
then <code class="sourceCode cpp">iterator_concept</code> denotes
<code class="sourceCode cpp">contiguous_iterator_tag</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.2)</a></span>
Otherwise, if <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>random_access</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>random_access</code>,
then <code class="sourceCode cpp">iterator_concept</code> denotes
<code class="sourceCode cpp">random_access_iterator_tag</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.3)</a></span>
Otherwise, if <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>bidirectional</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>bidirectional</code>,
then <code class="sourceCode cpp">iterator_concept</code> denotes
<code class="sourceCode cpp">bidirectional_iterator_tag</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.4)</a></span>
Otherwise, if <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>forward</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>forward</code>,
then <code class="sourceCode cpp">iterator_concept</code> denotes
<code class="sourceCode cpp">forward_iterator_tag</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.5)</a></span>
Otherwise, <code class="sourceCode cpp">iterator_concept</code> denotes
<code class="sourceCode cpp">input_iterator_tag</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
The member typedef-name
<code class="sourceCode cpp">iterator_category</code> is defined if and
only if <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>forward</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>forward</code>.
In that case, <code class="sourceCode cpp"><em>iterator</em>​<span class="op">::</span>​iterator_category</code>
is defined as follows:</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.1)</a></span> If
<code class="sourceCode cpp">is_reference_v<span class="op">&lt;</span>Ref<span class="op">&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>, and
<code class="sourceCode cpp">iterator_concept</code> is
<code class="sourceCode cpp">contiguous_iterator_tag</code>, then
<code class="sourceCode cpp">iterator_category</code> denotes
<code class="sourceCode cpp">random_access_iterator_tag</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.2)</a></span>
Otherwise, if <code class="sourceCode cpp">is_reference_v<span class="op">&lt;</span>Ref<span class="op">&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
then <code class="sourceCode cpp">iterator_category</code> denotes
<code class="sourceCode cpp">iterator_concept</code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.3)</a></span>
Otherwise, <code class="sourceCode cpp">iterator_category</code> denotes
<code class="sourceCode cpp">input_iterator_tag</code>.</p></li>
</ul>
<div class="sourceCode" id="cb53"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <em>iterator</em><span class="op">()</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>Postconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has no <em>target iterator object</em>.</p>
</div>
<div class="sourceCode" id="cb54"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> Ref <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<em>Preconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has a <em>target iterator object</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb55"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span>Ref<span class="op">&gt;(*</span>it<span class="op">)</span>;</span></code></pre></div>
<p>where <code class="sourceCode cpp">it</code> is an lvalue designating
the <em>target iterator object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code></p>
</div>
<div class="sourceCode" id="cb56"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-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>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
<em>Preconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has a <em>target iterator object</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb57"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a><span class="op">++</span>it;</span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span></code></pre></div>
<p>where <code class="sourceCode cpp">it</code> is an lvalue designating
the <em>target iterator object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code></p>
</div>
<div class="sourceCode" id="cb58"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-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>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
<em>Effects</em>: Equivalent to: <code class="sourceCode cpp"><span class="op">++(*</span><span class="kw">this</span><span class="op">)</span>;</code></p>
</div>
<div class="sourceCode" id="cb59"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span> <span class="kw">requires</span> <em>see below</em>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb60"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> tmp <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb60-2"><a href="#cb60-2" aria-hidden="true" tabindex="-1"></a><span class="op">++(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb60-3"><a href="#cb60-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> tmp;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">10</a></span>
<em>Remarks</em>: The expression in the requires-clause is equivalent
to:</p>
<div class="sourceCode" id="cb61"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a>Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>forward <span class="op">==</span> any_view_options<span class="op">::</span>forward </span></code></pre></div>
</div>
<div class="sourceCode" id="cb62"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb62-1"><a href="#cb62-1" aria-hidden="true" tabindex="-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>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">11</a></span>
<em>Constraints</em>: <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>bidirectional</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>bidirectional</code></p>
<p><span class="marginalizedparent"><a class="marginalized">12</a></span>
<em>Preconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has a <em>target iterator object</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">13</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb63"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb63-1"><a href="#cb63-1" aria-hidden="true" tabindex="-1"></a><span class="op">--</span>it;</span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span></code></pre></div>
<p>where <code class="sourceCode cpp">it</code> is an lvalue designating
the <em>target iterator object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code></p>
</div>
<div class="sourceCode" id="cb64"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb64-1"><a href="#cb64-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">--(</span><span class="dt">int</span><span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">14</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb65"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb65-1"><a href="#cb65-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> tmp <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb65-2"><a href="#cb65-2" aria-hidden="true" tabindex="-1"></a><span class="op">--(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb65-3"><a href="#cb65-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> tmp;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb66"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb66-1"><a href="#cb66-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <em>iterator</em><span class="op">&amp;</span> <span class="kw">operator</span><span class="op">+=(</span>difference_type n<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">15</a></span>
<em>Constraints</em>: <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>random_access</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>random_access</code></p>
<p><span class="marginalizedparent"><a class="marginalized">16</a></span>
<em>Preconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has a <em>target iterator object</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">17</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb67"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb67-1"><a href="#cb67-1" aria-hidden="true" tabindex="-1"></a>it <span class="op">+=</span> n;</span>
<span id="cb67-2"><a href="#cb67-2" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span></code></pre></div>
<p>where <code class="sourceCode cpp">it</code> is an lvalue designating
the <em>target iterator object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code></p>
</div>
<div class="sourceCode" id="cb68"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb68-1"><a href="#cb68-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <em>iterator</em><span class="op">&amp;</span> <span class="kw">operator</span><span class="op">-=(</span>difference_type n<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">18</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb69"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb69-1"><a href="#cb69-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> tmp <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb69-2"><a href="#cb69-2" aria-hidden="true" tabindex="-1"></a><span class="op">--(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb69-3"><a href="#cb69-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> tmp;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb70"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb70-1"><a href="#cb70-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> Ref <span class="kw">operator</span><span class="op">[](</span>difference_type n<span class="op">)</span> <span class="kw">const</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">19</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb71"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb71-1"><a href="#cb71-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="op">*((*</span><span class="kw">this</span><span class="op">)</span> <span class="op">+</span> n<span class="op">)</span>;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb72"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb72-1"><a href="#cb72-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> add_pointer_t<span class="op">&lt;</span>Ref<span class="op">&gt;</span> <span class="kw">operator</span><span class="op">-&gt;()</span> <span class="kw">const</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">20</a></span>
<em>Constraints</em>: <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>contiguous</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>contiguous</code></p>
<p><span class="marginalizedparent"><a class="marginalized">21</a></span>
<em>Preconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has a <em>target iterator object</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">22</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb73"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb73-1"><a href="#cb73-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> to_address<span class="op">(</span>it<span class="op">)</span>;</span></code></pre></div>
<p>where <code class="sourceCode cpp">it</code> is an lvalue designating
the <em>target iterator object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code></p>
</div>
<div class="sourceCode" id="cb74"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb74-1"><a href="#cb74-1" aria-hidden="true" tabindex="-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>iterator</em><span class="op">&amp;</span> y<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">20</a></span>
<em>Constraints</em>: <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>forward</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>forward</code></p>
<p><span class="marginalizedparent"><a class="marginalized">21</a></span>
<em>Effects</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(21.1)</a></span> If
both <code class="sourceCode cpp">x</code> and
<code class="sourceCode cpp">y</code> have no <em>target iterator
object</em>, equivalent to:</li>
</ul>
<div class="sourceCode" id="cb75"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb75-1"><a href="#cb75-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="kw">true</span>;</span></code></pre></div>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(21.2)</a></span>
Otherwise, if <code class="sourceCode cpp">x</code> has no <em>target
iterator object</em> and <code class="sourceCode cpp">y</code> has a
<em>target iterator object</em>, or,
<code class="sourceCode cpp">x</code> has a <em>target iterator
object</em> and <code class="sourceCode cpp">y</code> has no <em>target
iterator object</em>, equivalent to:</li>
</ul>
<div class="sourceCode" id="cb76"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb76-1"><a href="#cb76-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="kw">false</span>;</span></code></pre></div>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(21.3)</a></span>
Otherwise, let <code class="sourceCode cpp">it1</code> be an lvalue
designating the <em>target iterator object</em> of
<code class="sourceCode cpp">x</code>, and
<code class="sourceCode cpp">it2</code> be an lvalue designating the
<em>target iterator object</em> of
<code class="sourceCode cpp">y</code>.</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(21.3.1)</a></span>
If <code class="sourceCode cpp">is_same_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>it1<span class="op">)</span>, <span class="kw">decltype</span><span class="op">(</span>it2<span class="op">)&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code>,
equivalent to</li>
</ul>
<div class="sourceCode" id="cb77"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb77-1"><a href="#cb77-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="kw">false</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">(21.3.2)</a></span>
Otherwise, equivalent to</p>
<div class="sourceCode" id="cb78"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb78-1"><a href="#cb78-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> it1 <span class="op">==</span> it2;</span></code></pre></div></li>
</ul>
</div>
<div class="sourceCode" id="cb79"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb79-1"><a href="#cb79-1" aria-hidden="true" tabindex="-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">&lt;(</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></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">22</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb80"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb80-1"><a href="#cb80-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="op">(</span>x <span class="op">-</span> y<span class="op">)</span> <span class="op">&lt;</span> <span class="dv">0</span>;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb81"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb81-1"><a href="#cb81-1" aria-hidden="true" tabindex="-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">&gt;(</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></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">23</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb82"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb82-1"><a href="#cb82-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="op">(</span>x <span class="op">-</span> y<span class="op">)</span> <span class="op">&gt;</span> <span class="dv">0</span>;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb83"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb83-1"><a href="#cb83-1" aria-hidden="true" tabindex="-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">&lt;=(</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></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">24</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb84"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb84-1"><a href="#cb84-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="op">(</span>x <span class="op">-</span> y<span class="op">)</span> <span class="op">&lt;=</span> <span class="dv">0</span>;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb85"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb85-1"><a href="#cb85-1" aria-hidden="true" tabindex="-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">&gt;=(</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></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">25</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb86"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb86-1"><a href="#cb86-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="op">(</span>x <span class="op">-</span> y<span class="op">)</span> <span class="op">&gt;=</span> <span class="dv">0</span>;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb87"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb87-1"><a href="#cb87-1" aria-hidden="true" tabindex="-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">+(</span><em>iterator</em> i, difference_type n<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">26</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb88"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb88-1"><a href="#cb88-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> temp <span class="op">=</span> i;</span>
<span id="cb88-2"><a href="#cb88-2" aria-hidden="true" tabindex="-1"></a>temp <span class="op">+=</span> n;</span>
<span id="cb88-3"><a href="#cb88-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> temp;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb89"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb89-1"><a href="#cb89-1" aria-hidden="true" tabindex="-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">+(</span>difference_type n, <em>iterator</em> i<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">27</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb90"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb90-1"><a href="#cb90-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> i <span class="op">+</span> n;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb91"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb91-1"><a href="#cb91-1" aria-hidden="true" tabindex="-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">-(</span><em>iterator</em> i, difference_type n<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">28</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb92"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb92-1"><a href="#cb92-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> temp <span class="op">=</span> i;</span>
<span id="cb92-2"><a href="#cb92-2" aria-hidden="true" tabindex="-1"></a>temp <span class="op">-=</span> n;</span>
<span id="cb92-3"><a href="#cb92-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> temp;</span></code></pre></div>
</div>
<div class="sourceCode" id="cb93"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb93-1"><a href="#cb93-1" aria-hidden="true" tabindex="-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> difference_type <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>iterator</em><span class="op">&amp;</span> y<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">29</a></span>
<em>Constraints</em>: <code class="sourceCode cpp">Opts <span class="op">&amp;</span> any_view_options<span class="op">::</span>random_access</code>
is <code class="sourceCode cpp">any_view_options<span class="op">::</span>random_access</code></p>
<p><span class="marginalizedparent"><a class="marginalized">30</a></span>
<em>Preconditions</em>: Both <code class="sourceCode cpp">x</code> and
<code class="sourceCode cpp">y</code> have a <em>target iterator
object</em>, and the two <em>target iterator object</em>s have the same
type.</p>
<p><span class="marginalizedparent"><a class="marginalized">31</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb94"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb94-1"><a href="#cb94-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> it1 <span class="op">-</span> it2;</span></code></pre></div>
<p>where <code class="sourceCode cpp">it1</code> is an lvalue
designating the <em>target iterator object</em> of
<code class="sourceCode cpp">x</code>, and
<code class="sourceCode cpp">it2</code> is an lvalue designating the
<code class="sourceCode cpp"><span class="op">*</span>target iterator object<span class="op">*</span></code>
of <code class="sourceCode cpp">y</code>.</p>
</div>
<div class="sourceCode" id="cb95"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb95-1"><a href="#cb95-1" aria-hidden="true" tabindex="-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> RValueRef iter_move<span class="op">(</span><span class="kw">const</span> <em>iterator</em> <span class="op">&amp;</span>iter<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">32</a></span>
<em>Preconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has a <em>target iterator object</em>.</p>
<p><span class="marginalizedparent"><a class="marginalized">33</a></span>
<em>Effects</em>: Equivalent to:</p>
<div class="sourceCode" id="cb96"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb96-1"><a href="#cb96-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span>RValueRef<span class="op">&gt;(</span>ranges<span class="op">::</span>iter_move<span class="op">(</span>it<span class="op">))</span>;</span></code></pre></div>
<p>where <code class="sourceCode cpp">it</code> is an lvalue designating
the <em>target iterator object</em> of <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code></p>
</div>
<h4 class="unnumbered" id="class-any_viewsentinel-range.any.sentinel">?.?.?.8 Class
any_view::sentinel [range.any.sentinel]<a href="#class-any_viewsentinel-range.any.sentinel" class="self-link"></a></h4>
<div class="sourceCode" id="cb97"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb97-1"><a href="#cb97-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb97-2"><a href="#cb97-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Element,</span>
<span id="cb97-3"><a href="#cb97-3" aria-hidden="true" tabindex="-1"></a>            any_view_options Opts <span class="op">=</span> any_view_options<span class="op">::</span>input,</span>
<span id="cb97-4"><a href="#cb97-4" aria-hidden="true" tabindex="-1"></a>            <span class="kw">class</span> Ref <span class="op">=</span> Element<span class="op">&amp;</span>,</span>
<span id="cb97-5"><a href="#cb97-5" aria-hidden="true" tabindex="-1"></a>            <span class="kw">class</span> RValueRef <span class="op">=</span> <em>rvalue-ref-t</em><span class="op">&lt;</span>Ref<span class="op">&gt;</span>,</span>
<span id="cb97-6"><a href="#cb97-6" aria-hidden="true" tabindex="-1"></a>            <span class="kw">class</span> Diff <span class="op">=</span> <span class="dt">ptrdiff_t</span><span class="op">&gt;</span></span>
<span id="cb97-7"><a href="#cb97-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> any_view<span class="op">&lt;</span>Element, Opts, Ref, RValueRef, Diff<span class="op">&gt;::</span><em>sentinel</em> <span class="op">{</span></span>
<span id="cb97-8"><a href="#cb97-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">public</span><span class="op">:</span></span>
<span id="cb97-9"><a href="#cb97-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>sentinel</em><span class="op">()</span>;</span>
<span id="cb97-10"><a href="#cb97-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb97-11"><a href="#cb97-11" aria-hidden="true" tabindex="-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>
<span id="cb97-12"><a href="#cb97-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb97-13"><a href="#cb97-13" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb97-14"><a href="#cb97-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb98"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb98-1"><a href="#cb98-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <em>sentinel</em><span class="op">()</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<em>Postconditions</em>: <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>
has no <em>target sentinel object</em>.</p>
</div>
<div class="sourceCode" id="cb99"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb99-1"><a href="#cb99-1" aria-hidden="true" tabindex="-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>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>Effects</em>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(2.1)</a></span> If
either <code class="sourceCode cpp">x</code> has no <em>target iterator
object</em>, or <code class="sourceCode cpp">y</code> has a <em>target
sentinel object</em>, equivalent to:</li>
</ul>
<div class="sourceCode" id="cb100"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb100-1"><a href="#cb100-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="kw">false</span>;</span></code></pre></div>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.2)</a></span>
Otherwise, let <code class="sourceCode cpp">it</code> be an lvalue
designating the <em>target iterator object</em> of
<code class="sourceCode cpp">x</code>, and
<code class="sourceCode cpp">st</code> be an lvalue designating the
<em>target sentinel object</em> of
<code class="sourceCode cpp">y</code>,</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.3.1)</a></span> If
<code class="sourceCode cpp">sentinel_for<span class="op">&lt;</span>decay_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>st<span class="op">)&gt;</span>, decay_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>it<span class="op">)&gt;&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code>,
the return value is unspecified</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.3.2)</a></span>
Otherwise, equivalent to:</p></li>
</ul>
<div class="sourceCode" id="cb101"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb101-1"><a href="#cb101-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> it <span class="op">==</span> st;</span></code></pre></div></li>
</ul>
</div>
<style>
.bq{
    display: block;
    margin-block-start: 1em;
    margin-block-end: 1em;
    margin-inline-start: 40px;
    margin-inline-end: 40px;
}
</style>
<h1 data-number="10" id="bibliography"><span class="header-section-number">10</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-bemanproject" class="csl-entry" role="doc-biblioentry">
[beman-project] Patrick Roberts. A generalized type-erased view with
customizable properties. <a href="https://github.com/bemanproject/any_view"><div class="csl-block">https://github.com/bemanproject/any_view</div></a>
</div>
<div id="ref-ours" class="csl-entry" role="doc-biblioentry">
[ours] Hui Xie, S. Levent Yilmaz, and Dionne Louis. A proof-of-concept
implementation of <code class="sourceCode cpp">any_view</code>. <a href="https://github.com/huixie90/cpp_papers/tree/main/impl/any_view"><div class="csl-block">https://github.com/huixie90/cpp_papers/tree/main/impl/any_view</div></a>
</div>
<div id="ref-rangev3" class="csl-entry" role="doc-biblioentry">
[range-v3] Eric Niebler. range-v3 library. <a href="https://github.com/ericniebler/range-v3"><div class="csl-block">https://github.com/ericniebler/range-v3</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
