<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-03-20" />
  <title>`views::concat`</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 default">views::concat</code></h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2542R8</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-03-20</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, LWG<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>
      S. Levent Yilmaz<br>&lt;<a href="mailto:levent.yilmaz@gmail.com" class="email">levent.yilmaz@gmail.com</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="#r8" id="toc-r8"><span class="toc-section-number">1.1</span> R8<span></span></a></li>
<li><a href="#r7" id="toc-r7"><span class="toc-section-number">1.2</span> R7<span></span></a></li>
<li><a href="#r6" id="toc-r6"><span class="toc-section-number">1.3</span> R6<span></span></a></li>
<li><a href="#r5" id="toc-r5"><span class="toc-section-number">1.4</span> R5<span></span></a></li>
<li><a href="#r4" id="toc-r4"><span class="toc-section-number">1.5</span> R4<span></span></a></li>
<li><a href="#r3" id="toc-r3"><span class="toc-section-number">1.6</span> R3<span></span></a></li>
<li><a href="#r2" id="toc-r2"><span class="toc-section-number">1.7</span> R2<span></span></a></li>
<li><a href="#r1" id="toc-r1"><span class="toc-section-number">1.8</span> R1<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-and-examples" id="toc-motivation-and-examples"><span class="toc-section-number">3</span> Motivation and
Examples<span></span></a></li>
<li><a href="#design" id="toc-design"><span class="toc-section-number">4</span> Design<span></span></a>
<ul>
<li><a href="#concatable-ity-of-ranges" id="toc-concatable-ity-of-ranges"><span class="toc-section-number">4.1</span>
<code class="sourceCode default">concatable</code>-ity of
ranges<span></span></a>
<ul>
<li><a href="#reference" id="toc-reference"><span class="toc-section-number">4.1.1</span>
<code class="sourceCode default">reference</code><span></span></a></li>
<li><a href="#value_type" id="toc-value_type"><span class="toc-section-number">4.1.2</span>
<code class="sourceCode default">value_type</code><span></span></a></li>
<li><a href="#range_rvalue_reference_t" id="toc-range_rvalue_reference_t"><span class="toc-section-number">4.1.3</span>
<code class="sourceCode default">range_rvalue_reference_t</code><span></span></a></li>
<li><a href="#indirectly_readable" id="toc-indirectly_readable"><span class="toc-section-number">4.1.4</span>
<code class="sourceCode default">indirectly_readable</code><span></span></a></li>
<li><a href="#mixing-ranges-of-references-with-ranges-of-prvalues" id="toc-mixing-ranges-of-references-with-ranges-of-prvalues"><span class="toc-section-number">4.1.5</span> Mixing ranges of references with
ranges of prvalues<span></span></a></li>
<li><a href="#unsupported-cases-and-potential-extensions-for-the-future" id="toc-unsupported-cases-and-potential-extensions-for-the-future"><span class="toc-section-number">4.1.6</span> Unsupported Cases and Potential
Extensions for the Future<span></span></a></li>
</ul></li>
<li><a href="#zero-or-one-view" id="toc-zero-or-one-view"><span class="toc-section-number">4.2</span> Zero or one
view<span></span></a></li>
<li><a href="#hidden-on-time-complexity-for-n-adapted-ranges" id="toc-hidden-on-time-complexity-for-n-adapted-ranges"><span class="toc-section-number">4.3</span> Hidden <em>O(N)</em> time
complexity for <em>N</em> adapted ranges<span></span></a></li>
<li><a href="#borrowed-vs-cheap-iterator" id="toc-borrowed-vs-cheap-iterator"><span class="toc-section-number">4.4</span> Borrowed vs Cheap
Iterator<span></span></a></li>
<li><a href="#common-range" id="toc-common-range"><span class="toc-section-number">4.5</span> Common Range<span></span></a>
<ul>
<li><a href="#discussion-consolidate-with-cartesian_product_view" id="toc-discussion-consolidate-with-cartesian_product_view"><span class="toc-section-number">4.5.1</span> Discussion: Consolidate with
<code class="sourceCode default">cartesian_product_view</code><span></span></a></li>
<li><a href="#common_range-random_accessed_range-sized_range" id="toc-common_range-random_accessed_range-sized_range"><span class="toc-section-number">4.5.2</span> <code class="sourceCode default">!common_range &amp;&amp; (random_accessed_range &amp;&amp; sized_range)</code><span></span></a></li>
</ul></li>
<li><a href="#random-access-range" id="toc-random-access-range"><span class="toc-section-number">4.6</span> Random Access
Range<span></span></a></li>
<li><a href="#sized-range" id="toc-sized-range"><span class="toc-section-number">4.7</span> Sized Range<span></span></a></li>
<li><a href="#iter_swap-customizations" id="toc-iter_swap-customizations"><span class="toc-section-number">4.8</span>
<code class="sourceCode default">iter_swap</code>
Customizations<span></span></a>
<ul>
<li><a href="#option-1-delegate-to-the-underlying-iter_swap" id="toc-option-1-delegate-to-the-underlying-iter_swap"><span class="toc-section-number">4.8.1</span> Option 1: Delegate to the
Underlying
<code class="sourceCode default">iter_swap</code><span></span></a></li>
<li><a href="#option-2-do-not-provide-the-customization" id="toc-option-2-do-not-provide-the-customization"><span class="toc-section-number">4.8.2</span> Option 2: Do not Provide the
Customization<span></span></a></li>
<li><a href="#option-3-delegate-to-the-underlying-iter_swap-only-if-they-have-the-same-type" id="toc-option-3-delegate-to-the-underlying-iter_swap-only-if-they-have-the-same-type"><span class="toc-section-number">4.8.3</span> Option 3: Delegate to the
Underlying <code class="sourceCode default">iter_swap</code> Only If
They Have the Same Type<span></span></a></li>
</ul></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">4.9</span> Implementation
Experience<span></span></a></li>
</ul></li>
<li><a href="#wording" id="toc-wording"><span class="toc-section-number">5</span> Wording<span></span></a>
<ul>
<li><a href="#addition-to-ranges" id="toc-addition-to-ranges"><span class="toc-section-number">5.1</span> Addition to
<code class="sourceCode default">&lt;ranges&gt;</code><span></span></a></li>
<li><a href="#move-exposition-only-utilities" id="toc-move-exposition-only-utilities"><span class="toc-section-number">5.2</span> Move exposition-only
utilities<span></span></a></li>
<li><a href="#concat" id="toc-concat"><span class="toc-section-number">5.3</span>
<code class="sourceCode default">concat</code><span></span></a>
<ul>
<li><a href="#concat-view-range.concat" id="toc-concat-view-range.concat">?.?.? Concat view
[range.concat]<span></span></a></li>
</ul></li>
<li><a href="#feature-test-macro" id="toc-feature-test-macro"><span class="toc-section-number">5.4</span> Feature Test
Macro<span></span></a></li>
</ul></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">6</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="r8"><span class="header-section-number">1.1</span> R8<a href="#r8" class="self-link"></a></h2>
<ul>
<li>requires expression update in
<code class="sourceCode default">operator-(it, default_sentinel)</code></li>
<li>Various minor wording fixes</li>
</ul>
<h2 data-number="1.2" id="r7"><span class="header-section-number">1.2</span> R7<a href="#r7" class="self-link"></a></h2>
<ul>
<li>update wording w.r.t <code class="sourceCode default">!common_range &amp;&amp; random_access_range &amp;&amp; sized_range</code>
changes</li>
<li>fix const-conversion constructor</li>
<li>Various wording fixes</li>
</ul>
<h2 data-number="1.3" id="r6"><span class="header-section-number">1.3</span> R6<a href="#r6" class="self-link"></a></h2>
<ul>
<li>Added a section <code class="sourceCode default">!common_range &amp;&amp; random_access_range &amp;&amp; sized_range</code></li>
</ul>
<h2 data-number="1.4" id="r5"><span class="header-section-number">1.4</span> R5<a href="#r5" class="self-link"></a></h2>
<ul>
<li>Removed <code class="sourceCode default">concat_expert</code>
(reverting to R3) per SG9 poll.</li>
<li>Fix <code class="sourceCode default">static_cast&lt;difference_type&gt;</code></li>
<li>Reuse utilities in
<code class="sourceCode default">cartesian_product_view</code> to define
<code class="sourceCode default">concat-is-bidirectional</code></li>
<li>Various wording fixes</li>
</ul>
<h2 data-number="1.5" id="r4"><span class="header-section-number">1.5</span> R4<a href="#r4" class="self-link"></a></h2>
<ul>
<li>Add <code class="sourceCode default">concat_expert</code></li>
</ul>
<h2 data-number="1.6" id="r3"><span class="header-section-number">1.6</span> R3<a href="#r3" class="self-link"></a></h2>
<ul>
<li>Redesigned <code class="sourceCode default">iter_swap</code></li>
<li>Relaxed <code class="sourceCode default">random_access_range</code>
constraints</li>
<li>Fixed conversions of
<code class="sourceCode default">difference</code> types</li>
<li>Various wording fixes</li>
</ul>
<h2 data-number="1.7" id="r2"><span class="header-section-number">1.7</span> R2<a href="#r2" class="self-link"></a></h2>
<ul>
<li>Adding extra semantic constraints in the concept
<code class="sourceCode default">concat-indirectly-readable</code> to
prevent non-equality-preserving behaviour of
<code class="sourceCode default">operator*</code> and
<code class="sourceCode default">iter_move</code>.</li>
</ul>
<h2 data-number="1.8" id="r1"><span class="header-section-number">1.8</span> R1<a href="#r1" class="self-link"></a></h2>
<ul>
<li><p>Removed the <code class="sourceCode default">common_range</code>
support for underlying ranges that are <code class="sourceCode default">!common_range &amp;&amp; random_access_range &amp;&amp; sized_range</code>.</p></li>
<li><p>Introduced extra exposition concepts to simplify the wording that
defines <code class="sourceCode default">concatable</code>.</p></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
<code class="sourceCode default">views::concat</code> as very briefly
introduced in Section 4.7 of <span class="citation" data-cites="P2214R1">[<a href="#ref-P2214R1" role="doc-biblioref">P2214R1</a>]</span>. It is a view factory that
takes an arbitrary number of ranges as an argument list, and provides a
view that starts at the first element of the first range, ends at the
last element of the last range, with all range elements sequenced in
between respectively in the order given in the arguments, effectively
concatenating, or chaining together the argument ranges.</p>
<h1 data-number="3" id="motivation-and-examples"><span class="header-section-number">3</span> Motivation and Examples<a href="#motivation-and-examples" class="self-link"></a></h1>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> v1<span class="op">{</span><span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span><span class="op">}</span>, v2<span class="op">{</span><span class="dv">4</span>,<span class="dv">5</span><span class="op">}</span>, v3<span class="op">{}</span>;</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>array  a<span class="op">{</span><span class="dv">6</span>,<span class="dv">7</span>,<span class="dv">8</span><span class="op">}</span>;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> s <span class="op">=</span> <span class="dv">9</span>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;[{:n}, {:n}, {:n}, {:n}, {}]</span><span class="sc">\n</span><span class="st">&quot;</span>, </span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>            v1, v2, v3, a, s<span class="op">)</span>; </span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="co">// output:  [1, 2, 3, 4, 5, <strong>,</strong> 6, 7, 8, 9]</span></span></code></pre></div>

</div></td>
<td><div>

<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>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> v1<span class="op">{</span><span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span><span class="op">}</span>, v2<span class="op">{</span><span class="dv">4</span>,<span class="dv">5</span><span class="op">}</span>, v3<span class="op">{}</span>;</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>array  a<span class="op">{</span><span class="dv">6</span>,<span class="dv">7</span>,<span class="dv">8</span><span class="op">}</span>;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> s <span class="op">=</span> std<span class="op">::</span>views<span class="op">::</span>single<span class="op">(</span><span class="dv">9</span><span class="op">)</span>;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;{}</span><span class="sc">\n</span><span class="st">&quot;</span>, </span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>            std<span class="op">::</span>views<span class="op">::</span>concat<span class="op">(</span>v1, v2, v3, a, s<span class="op">))</span>; </span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="co">// output:  [1, 2, 3, 4, 5, 6, 7, 8, 9]</span></span></code></pre></div>

</div></td>
</tr>
<tr class="even">
<td><div>

<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><span class="kw">class</span> Foo;</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Bar<span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> Foo<span class="op">&amp;</span> getFoo<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> MyClass<span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>Foo<span class="op">&gt;</span> foos_;</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>  Bar bar_;</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> getFoos <span class="op">()</span> <span class="kw">const</span><span class="op">{</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>reference_wrapper<span class="op">&lt;</span>Foo <span class="kw">const</span><span class="op">&gt;&gt;</span> fooRefs;</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>    fooRefs<span class="op">.</span>reserve<span class="op">(</span>foos_<span class="op">.</span>size<span class="op">()</span> <span class="op">+</span> <span class="dv">1</span><span class="op">)</span>;</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> <span class="kw">const</span><span class="op">&amp;</span> f <span class="op">:</span> foos_<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>      fooRefs<span class="op">.</span>emplace_back<span class="op">(</span>f<span class="op">)</span>;</span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>    fooRefs<span class="op">.</span>emplace_back<span class="op">(</span>bar_<span class="op">.</span>getFoo<span class="op">())</span>;</span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> fooRefs;</span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a><span class="co">// user</span></span>
<span id="cb3-25"><a href="#cb3-25" 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> foo<span class="op">:</span> myClass<span class="op">.</span>getFoos<span class="op">()){</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>  <span class="co">// `foo` is std::reference_wrapper&lt;Foo const&gt;, not simply a Foo</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
<td><div>

<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">class</span> Foo;</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Bar<span class="op">{</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> Foo<span class="op">&amp;</span> getFoo<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> MyClass<span class="op">{</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>vector<span class="op">&lt;</span>Foo<span class="op">&gt;</span> foos_;</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>  Bar bar_;</span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> getFoos <span class="op">()</span> <span class="kw">const</span><span class="op">{</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> std<span class="op">::</span>views<span class="op">::</span>concat<span class="op">(</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>      foos_,</span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a>      std<span class="op">::</span>views<span class="op">::</span>single<span class="op">(</span>std<span class="op">::</span>cref<span class="op">(</span>bar_<span class="op">))</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>      <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">(&amp;</span>Bar<span class="op">::</span>getFoo<span class="op">)</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>    <span class="op">)</span>;</span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a><span class="co">// user</span></span>
<span id="cb4-22"><a href="#cb4-22" 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> foo<span class="op">:</span> myClass<span class="op">.</span>getFoos<span class="op">()){</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>  <span class="co">// use foo, which is Foo const &amp;</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>The first example shows that dealing with multiple ranges require
care even in the simplest of cases: The “Before” version manually
concatenates all the ranges in a formatting string, but empty ranges
aren’t handled and the result contains an extra comma and a space. With
<code class="sourceCode default">concat_view</code>, empty ranges are
handled per design, and the construct expresses the intent cleanly and
directly.</p>
<p>In the second example, the user has a class composed of fragmented
and indirect data. They want to implement a member function that
provides a range-like view to all this data sequenced together in some
order, and without creating any copies. The “Before” implementation is
needlessly complex and creates a temporary container with a potentially
problematic indirection in its value type.
<code class="sourceCode default">concat_view</code> based implementation
is a neat one-liner.</p>
<h1 data-number="4" id="design"><span class="header-section-number">4</span> Design<a href="#design" class="self-link"></a></h1>
<p>This is a generator factory as described in <span class="citation" data-cites="P2214R1">[<a href="#ref-P2214R1" role="doc-biblioref">P2214R1</a>]</span> Section 4.7. As such, it can
not be piped to. It takes the list of ranges to concatenate as arguments
to <code class="sourceCode default">ranges::concat_view</code>
constructor, or to
<code class="sourceCode default">ranges::views::concat</code>
customization point object.</p>
<h2 data-number="4.1" id="concatable-ity-of-ranges"><span class="header-section-number">4.1</span>
<code class="sourceCode default">concatable</code>-ity of ranges<a href="#concatable-ity-of-ranges" class="self-link"></a></h2>
<p>Adaptability of any given two or more distinct
<code class="sourceCode default">range</code>s into a sequence that
itself models a <code class="sourceCode default">range</code>, depends
on the compatibility of the reference and the value types of these
ranges. A precise formulation is made in terms of
<code class="sourceCode default">std::common_reference_t</code> and
<code class="sourceCode default">std::common_type_t</code>, and is
captured by the exposition only concept
<code class="sourceCode default">concatable</code>. See <a href="#concatable-definition">Wording</a>. Proposed
<code class="sourceCode default">concat_view</code> is then additionally
constrained by this concept. (Note that, this is an improvement over
<span class="citation" data-cites="rangev3">[<a href="#ref-rangev3" role="doc-biblioref">range-v3</a>]</span>
<code class="sourceCode default">concat_view</code> which lacks such
constraints, and fails with hard errors instead.)</p>
<h3 data-number="4.1.1" id="reference"><span class="header-section-number">4.1.1</span>
<code class="sourceCode default">reference</code><a href="#reference" class="self-link"></a></h3>
<p>The <code class="sourceCode default">reference</code> type is the
<code class="sourceCode default">common_reference_t</code> of all
underlying range’s
<code class="sourceCode default">range_reference_t</code>. In addition,
as the result of
<code class="sourceCode default">common_reference_t</code> is not
necessarily a reference type, an extra constraint is needed to make sure
that each underlying range’s
<code class="sourceCode default">range_reference_t</code> is convertible
to that common reference.</p>
<h3 data-number="4.1.2" id="value_type"><span class="header-section-number">4.1.2</span>
<code class="sourceCode default">value_type</code><a href="#value_type" class="self-link"></a></h3>
<p>To support the cases where underlying ranges have proxy iterators,
such as <code class="sourceCode default">zip_view</code>, the
<code class="sourceCode default">value_type</code> cannot simply be the
<code class="sourceCode default">remove_cvref_t</code> of the
<code class="sourceCode default">reference</code> type, and it needs to
respect underlying ranges’
<code class="sourceCode default">value_type</code>. Therefore, in this
proposal the <code class="sourceCode default">value_type</code> is
defined as the <code class="sourceCode default">common_type_t</code> of
all underlying range’s
<code class="sourceCode default">range_value_t</code>.</p>
<h3 data-number="4.1.3" id="range_rvalue_reference_t"><span class="header-section-number">4.1.3</span>
<code class="sourceCode default">range_rvalue_reference_t</code><a href="#range_rvalue_reference_t" class="self-link"></a></h3>
<p>To make <code class="sourceCode default">concat_view</code>’s
iterator’s <code class="sourceCode default">iter_move</code> behave
correctly for the cases where underlying iterators customise
<code class="sourceCode default">iter_move</code>, such as
<code class="sourceCode default">zip_view</code>,
<code class="sourceCode default">concat_view</code> has to respect those
customizations. Therefore,
<code class="sourceCode default">concat_view</code> requires
<code class="sourceCode default">common_reference_t</code> of all
underlying ranges’s
<code class="sourceCode default">range_rvalue_reference_t</code> exist
and can be converted to from each underlying range’s
<code class="sourceCode default">range_rvalue_reference_t</code>.</p>
<h3 data-number="4.1.4" id="indirectly_readable"><span class="header-section-number">4.1.4</span>
<code class="sourceCode default">indirectly_readable</code><a href="#indirectly_readable" class="self-link"></a></h3>
<p>In order to make <code class="sourceCode default">concat_view</code>
model <code class="sourceCode default">input_range</code>,
<code class="sourceCode default">reference</code>,
<code class="sourceCode default">value_type</code>, and
<code class="sourceCode default">range_rvalue_reference_t</code> have to
be constrained so that the iterator of the
<code class="sourceCode default">concat_view</code> models
<code class="sourceCode default">indirectly_readable</code>.</p>
<h3 data-number="4.1.5" id="mixing-ranges-of-references-with-ranges-of-prvalues"><span class="header-section-number">4.1.5</span> Mixing ranges of references
with ranges of prvalues<a href="#mixing-ranges-of-references-with-ranges-of-prvalues" class="self-link"></a></h3>
<p>In the following example,</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>std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span> v <span class="op">=</span> <span class="op">...</span>;</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> r1 <span class="op">=</span> v <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">([](</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> s<span class="op">)</span> <span class="op">-&gt;</span> std<span class="op">::</span>string<span class="op">&amp;&amp;</span> <span class="op">{</span><span class="cf">return</span> std<span class="op">::</span>move<span class="op">(</span>s<span class="op">)</span>;<span class="op">})</span>;</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> r2 <span class="op">=</span> std<span class="op">::</span>views<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">2</span><span class="op">)</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>            <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">([](</span><span class="kw">auto</span> i<span class="op">){</span><span class="cf">return</span> std<span class="op">::</span>to_string<span class="op">(</span>i<span class="op">)})</span>;</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> cv <span class="op">=</span> std<span class="op">::</span>views<span class="op">::</span>concat<span class="op">(</span>r1, r2<span class="op">)</span>;</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> it <span class="op">=</span> cv<span class="op">.</span>begin<span class="op">()</span>;</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="op">*</span>it; <span class="co">// first deref</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="op">*</span>it; <span class="co">// second deref</span></span></code></pre></div>
<p><code class="sourceCode default">r1</code> is a range of which
<code class="sourceCode default">range_reference_t</code> is
<code class="sourceCode default">std::string&amp;&amp;</code>, while
<code class="sourceCode default">r2</code>’s
<code class="sourceCode default">range_reference_t</code> is
<code class="sourceCode default">std::string</code>. The
<code class="sourceCode default">common_reference_t</code> between these
two <code class="sourceCode default">reference</code>s would be
<code class="sourceCode default">std::string</code>. After the “first
deref”, even though the result is unused, there is a conversion from
<code class="sourceCode default">std::string&amp;&amp;</code> to
<code class="sourceCode default">std::string</code> when the result of
underlying iterator’s <code class="sourceCode default">operator*</code>
is converted to the
<code class="sourceCode default">common_reference_t</code>. This is a
move construction and the underlying
<code class="sourceCode default">vector</code>’s element is modified to
a moved-from state. Later when the “second deref” is called, the result
is a moved-from <code class="sourceCode default">std::string</code>.
This breaks the “equality preserving” requirements.</p>
<p>Similar to <code class="sourceCode default">operator*</code>,
<code class="sourceCode default">ranges::iter_move</code> has this same
issue, and it is more common to run into this problem. For example,</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>std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>string<span class="op">&gt;</span> v <span class="op">=</span> <span class="op">...</span>;</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> r <span class="op">=</span> std<span class="op">::</span>views<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">2</span><span class="op">)</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>           <span class="op">|</span> std<span class="op">::</span>views<span class="op">::</span>transform<span class="op">([](</span><span class="kw">auto</span> i<span class="op">){</span><span class="cf">return</span> std<span class="op">::</span>to_string<span class="op">(</span>i<span class="op">)})</span>;</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> cv <span class="op">=</span> std<span class="op">::</span>views<span class="op">::</span>concat<span class="op">(</span>v, r<span class="op">)</span>;</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> it <span class="op">=</span> cv<span class="op">.</span>begin<span class="op">()</span>;</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>ranges<span class="op">::</span>iter_move<span class="op">(</span>it<span class="op">)</span>; <span class="co">// first iter_move</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>ranges<span class="op">::</span>iter_move<span class="op">(</span>it<span class="op">)</span>; <span class="co">// second iter_move</span></span></code></pre></div>
<p><code class="sourceCode default">v</code>’s
<code class="sourceCode default">range_rvalue_reference_t</code> is
<code class="sourceCode default">std::string&amp;&amp;</code>, and
<code class="sourceCode default">r</code>’s
<code class="sourceCode default">range_rvalue_reference_t</code> is
<code class="sourceCode default">std::string</code>, the
<code class="sourceCode default">common_reference_t</code> between them
is <code class="sourceCode default">std::string</code>. After the first
<code class="sourceCode default">iter_move</code>, the underlying
<code class="sourceCode default">vector</code>’s first element is moved
to construct the temporary
<code class="sourceCode default">common_reference_t</code>, aka
<code class="sourceCode default">std::string</code>. As a result, the
second <code class="sourceCode default">iter_move</code> results in a
moved-from state <code class="sourceCode default">std::string</code>.
This breaks the “non-modifying” equality-preserving contract in
<code class="sourceCode default">indirectly_readable</code> concept.</p>
<p>A naive solution for this problem is to ban all the usages of mixing
ranges of references with ranges of prvalues. However, not all of this
kind of mixing are problematic. For example,
<code class="sourceCode default">concat</code>ing a range of
<code class="sourceCode default">std::string&amp;&amp;</code> with a
range of prvalue
<code class="sourceCode default">std::string_view</code> is OK, because
converting <code class="sourceCode default">std::string&amp;&amp;</code>
to <code class="sourceCode default">std::string_view</code> does not
modify the
<code class="sourceCode default">std::string&amp;&amp;</code>. In
general, it is not possible to detect whether the conversion from
<code class="sourceCode default">T&amp;&amp;</code> to
<code class="sourceCode default">U</code> modifies
<code class="sourceCode default">T&amp;&amp;</code> through syntactic
requirements. Therefore, the authors of this paper propose to use the
“equality-preserving” semantic requirements of the requires-expression
and the notational convention that constant lvalues shall not be
modified in a manner observable to equality-preserving as defined in
<span>18.2
<a href="https://wg21.link/concepts.equality">[concepts.equality]</a></span>.
See <a href="#concat-indirectly-readable-definition">Wording</a>.</p>
<h3 data-number="4.1.6" id="unsupported-cases-and-potential-extensions-for-the-future"><span class="header-section-number">4.1.6</span> Unsupported Cases and
Potential Extensions for the Future<a href="#unsupported-cases-and-potential-extensions-for-the-future" class="self-link"></a></h3>
<p>Common type and reference based
<code class="sourceCode default">concatable</code> logic is a practical
and convenient solution that satisfies the motivation as outlined, and
is what the authors propose in this paper. However, there are several
potentially important use cases that get left out:</p>
<ol type="1">
<li>Concatenating ranges of different subclasses, into a range of their
common base.</li>
<li>Concatenating ranges of unrelated types into a range of a
user-determined common type, e.g. a
<code class="sourceCode default">std::variant</code>.</li>
</ol>
<p>Here is an example of the first case where
<code class="sourceCode default">common_reference</code> formulation can
manifest a rather counter-intuitive behavior: Let
<code class="sourceCode default">D1</code> and
<code class="sourceCode default">D2</code> be two types only related by
their common base <code class="sourceCode default">B</code>, and
<code class="sourceCode default">d1</code>,
<code class="sourceCode default">d2</code>, and
<code class="sourceCode default">b</code> be some range of these types,
respectively. <code class="sourceCode default">concat(b, d1, d2)</code>
is a well-formed range of <code class="sourceCode default">B</code> by
the current formulation, suggesting such usage is supported. However, a
mere reordering of the sequence, say to
<code class="sourceCode default">concat(d1, d2, b)</code>, yields one
that is not.</p>
<p>The authors believe that such cases should be supported, but can only
be done so via an adaptor that needs at least one explicit type argument
at its interface. A future extension may satisfy these use cases, for
example a <code class="sourceCode default">concat_as</code> view, or by
even generally via an <code class="sourceCode default">as</code> view
that is a type-generalized version of the
<code class="sourceCode default">as_const</code> view of <span class="citation" data-cites="P2278R1">[<a href="#ref-P2278R1" role="doc-biblioref">P2278R1</a>]</span>.</p>
<h2 data-number="4.2" id="zero-or-one-view"><span class="header-section-number">4.2</span> Zero or one view<a href="#zero-or-one-view" class="self-link"></a></h2>
<ul>
<li>No argument <code class="sourceCode default">views::concat()</code>
is ill-formed. It can not be a
<code class="sourceCode default">views::empty&lt;T&gt;</code> because
there is no reasonable way to determine an element type
<code class="sourceCode default">T</code>.</li>
<li>Single argument
<code class="sourceCode default">views::concat(r)</code> is expression
equivalent to <code class="sourceCode default">views::all(r)</code>,
which intuitively follows.</li>
</ul>
<h2 data-number="4.3" id="hidden-on-time-complexity-for-n-adapted-ranges"><span class="header-section-number">4.3</span> Hidden <em>O(N)</em> time
complexity for <em>N</em> adapted ranges<a href="#hidden-on-time-complexity-for-n-adapted-ranges" class="self-link"></a></h2>
<p>Time complexities as required by the
<code class="sourceCode default">ranges</code> concepts are formally
expressed with respect to the total number of elements (the size) of a
given range, and not to the statically known parameters of that range.
Hence, the complexity of
<code class="sourceCode default">concat_view</code> or its iterators’
operations are documented to be constant time, even though some of these
are a linear function of the number of ranges it concatenates which is a
statically known parameter of this view.</p>
<p>Some examples of these operations for
<code class="sourceCode default">concat_view</code> are copy,
<code class="sourceCode default">begin</code> and
<code class="sourceCode default">size</code>, and its iterators’
increment, decrement, advance, distance. This characteristic (but not
necessarily the specifics) are very much similar to the other n-ary
adaptors like <code class="sourceCode default">zip_view</code> <span class="citation" data-cites="P2321R2">[<a href="#ref-P2321R2" role="doc-biblioref">P2321R2</a>]</span> and
<code class="sourceCode default">cartesian_view</code> <span class="citation" data-cites="P2374R3">[<a href="#ref-P2374R3" role="doc-biblioref">P2374R3</a>]</span>.</p>
<h2 data-number="4.4" id="borrowed-vs-cheap-iterator"><span class="header-section-number">4.4</span> Borrowed vs Cheap Iterator<a href="#borrowed-vs-cheap-iterator" class="self-link"></a></h2>
<p><code class="sourceCode default">concat_view</code> can be designed
to be a <code class="sourceCode default">borrowed_range</code>, if all
the underlying ranges are. However, this requires the iterator
implementation to contain a copy of all iterators and sentinels of all
underlying ranges at all times (just like that of
<code class="sourceCode default">views::zip</code> <span class="citation" data-cites="P2321R2">[<a href="#ref-P2321R2" role="doc-biblioref">P2321R2</a>]</span>). On the other hand (unlike
<code class="sourceCode default">views::zip</code>), a much cheaper
implementation can satisfy all the proposed functionality provided it is
permitted to be unconditionally not borrowed. This implementation would
maintain only a single active iterator at a time and simply refers to
the parent view for the bounds.</p>
<p>Experience shows the borrowed-ness of
<code class="sourceCode default">concat</code> is not a major
requirement; and the existing implementation in <span class="citation" data-cites="rangev3">[<a href="#ref-rangev3" role="doc-biblioref">range-v3</a>]</span> seems to have picked the
cheaper alternative. This paper proposes the same.</p>
<h2 data-number="4.5" id="common-range"><span class="header-section-number">4.5</span> Common Range<a href="#common-range" class="self-link"></a></h2>
<p><code class="sourceCode default">concat_view</code> can be
<code class="sourceCode default">common_range</code> if the last
underlying range models
<code class="sourceCode default">common_range</code></p>
<h3 data-number="4.5.1" id="discussion-consolidate-with-cartesian_product_view"><span class="header-section-number">4.5.1</span> Discussion: Consolidate with
<code class="sourceCode default">cartesian_product_view</code><a href="#discussion-consolidate-with-cartesian_product_view" class="self-link"></a></h3>
<p>In the R0 version,
<code class="sourceCode default">concat_view</code> can be
<code class="sourceCode default">common_range</code> if the last
underlying range models <code class="sourceCode default">common_range || (random_access_range &amp;&amp; sized_range)</code></p>
<p>The <code class="sourceCode default">end</code> function was defined
as</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="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>common_range<span class="op">&lt;</span>last<span class="op">-</span>view<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> N <span class="op">=</span> <span class="kw">sizeof</span><span class="op">...(</span>Views<span class="op">)</span>;</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> iterator<span class="op">&lt;</span>is<span class="op">-</span><span class="kw">const</span><span class="op">&gt;{</span><span class="kw">this</span>, in_place_index<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;</span>, </span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>                      ranges<span class="op">::</span>end<span class="op">(</span>get<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;(</span>views_<span class="op">))}</span>;</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>random_access_range<span class="op">&lt;</span>last<span class="op">-</span>view<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> sized_range<span class="op">&lt;</span>last<span class="op">-</span>view<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> N <span class="op">=</span> <span class="kw">sizeof</span><span class="op">...(</span>Views<span class="op">)</span>;</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> iterator<span class="op">&lt;</span>is<span class="op">-</span><span class="kw">const</span><span class="op">&gt;{</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">this</span>, in_place_index<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;</span>,</span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>        ranges<span class="op">::</span>begin<span class="op">(</span>get<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;(</span>views_<span class="op">))</span> <span class="op">+</span> ranges<span class="op">::</span>size<span class="op">(</span>get<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;(</span>views_<span class="op">))}</span>;</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> default_sentinel;</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Following SG9’s direction, the <code class="sourceCode default">random_access_range &amp;&amp; sized_range</code>
was removed in R1 version for simplicity</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><span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>common_range<span class="op">&lt;</span>last<span class="op">-</span>view<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> N <span class="op">=</span> <span class="kw">sizeof</span><span class="op">...(</span>Views<span class="op">)</span>;</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> iterator<span class="op">&lt;</span>is<span class="op">-</span><span class="kw">const</span><span class="op">&gt;{</span><span class="kw">this</span>, in_place_index<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;</span>, </span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>                      ranges<span class="op">::</span>end<span class="op">(</span>get<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;(</span>views_<span class="op">))}</span>;</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> default_sentinel;</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>However,
<code class="sourceCode default">cartesian_product_view</code>
<span>26.7.32.2
<a href="https://wg21.link/range.cartesian.view">[range.cartesian.view]</a></span>
defines its <code class="sourceCode default">end</code> function in a
way that is very similar to
<code class="sourceCode default">concat_view</code>’s R0 version.</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>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> R<span class="op">&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> cartesian<span class="op">-</span>product<span class="op">-</span>common<span class="op">-</span>arg <span class="op">=</span>                <span class="co">// exposition only</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    common_range<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">||</span> <span class="op">(</span>sized_range<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> random_access_range<span class="op">&lt;</span>R<span class="op">&gt;)</span>;</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> First, <span class="kw">class</span><span class="op">...</span> Vs<span class="op">&gt;</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> cartesian<span class="op">-</span>product<span class="op">-</span>is<span class="op">-</span>common <span class="op">=</span>                 <span class="co">// exposition only</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    cartesian<span class="op">-</span>product<span class="op">-</span>common<span class="op">-</span>arg<span class="op">&lt;</span>First<span class="op">&gt;</span>;</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span>cartesian<span class="op">-</span>product<span class="op">-</span>common<span class="op">-</span>arg R<span class="op">&gt;</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> cartesian<span class="op">-</span>common<span class="op">-</span>arg<span class="op">-</span>end<span class="op">(</span>R<span class="op">&amp;</span> r<span class="op">)</span> <span class="op">{</span>       <span class="co">// exposition only</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>common_range<span class="op">&lt;</span>R<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> ranges<span class="op">::</span>end<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>r<span class="op">)</span> <span class="op">+</span> ranges<span class="op">::</span>distance<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> iterator<span class="op">&lt;</span><span class="kw">false</span><span class="op">&gt;</span> end<span class="op">()</span></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> <span class="op">((!</span>simple<span class="op">-</span>view<span class="op">&lt;</span>First<span class="op">&gt;</span> <span class="op">||</span> <span class="op">...</span> <span class="op">||</span> <span class="op">!</span>simple<span class="op">-</span>view<span class="op">&lt;</span>Vs<span class="op">&gt;)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a>        cartesian<span class="op">-</span>product<span class="op">-</span>is<span class="op">-</span>common<span class="op">&lt;</span>First, Vs<span class="op">...&gt;)</span>;</span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> iterator<span class="op">&lt;</span><span class="kw">true</span><span class="op">&gt;</span> end<span class="op">()</span> <span class="kw">const</span></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span> cartesian<span class="op">-</span>product<span class="op">-</span>is<span class="op">-</span>common<span class="op">&lt;</span><span class="kw">const</span> First, <span class="kw">const</span> Vs<span class="op">...&gt;</span>;</span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> default_sentinel_t end<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p>For consistency between
<code class="sourceCode default">cartesian_product_view</code> and
<code class="sourceCode default">concat_view</code>, it would be good to
add back the support of <code class="sourceCode default">random_access_range &amp;&amp; size_range</code>.
Those exposition only concepts and functions can be reused for both of
the views, and their definitions of
<code class="sourceCode default">end</code> function would be very
similar, except that
<code class="sourceCode default">cartesian_product_view</code> checks
the first underlying range and
<code class="sourceCode default">concat_view</code> checks the last
underlying range.</p>
<p>As per SG9 direction, this section is dropped.</p>
<h3 data-number="4.5.2" id="common_range-random_accessed_range-sized_range"><span class="header-section-number">4.5.2</span> <code class="sourceCode default">!common_range &amp;&amp; (random_accessed_range &amp;&amp; sized_range)</code><a href="#common_range-random_accessed_range-sized_range" class="self-link"></a></h3>
<p>In R0 version, <code class="sourceCode default">concat_view</code> is
a <code class="sourceCode default">common_range</code> if the last range
satisfies <code class="sourceCode default">common_range || (random_accessed_range &amp;&amp; sized_range)</code></p>
<p>As per SG9’s direction,
<code class="sourceCode default">concat_view</code> should not pretend
to be a <code class="sourceCode default">common_range</code>, when the
last underlying range is a <code class="sourceCode default">!common_range &amp;&amp; random_accessed_range &amp;&amp; sized_range</code>,
even though the end iterator could be computed from <code class="sourceCode default">ranges::begin(r) + ranges::size(r)</code>.</p>
<p>Therefore in the current version the
<code class="sourceCode default">common_range</code> is simplified
to,</p>
<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>concat<span class="op">-</span>is<span class="op">-</span>common <span class="op">=</span> common_range<span class="op">&lt;</span>last<span class="op">-</span>view<span class="op">&gt;</span></span></code></pre></div>
<p>However, the current design of
<code class="sourceCode default">concat_view</code>’s bidirectional
behaviour does use <code class="sourceCode default">ranges::begin(r) + ranges::size(r) - 1</code>
to get to the previous range’s last iterator, when the previous range is
<code class="sourceCode default">!common_range &amp;&amp; random_accessed_range &amp;&amp; sized_range</code>.
Its <code class="sourceCode default">bidirectional_range</code>
requirement is designed as follows</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">template</span> <span class="op">&lt;</span><span class="kw">class</span> R<span class="op">&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> common<span class="op">-</span>ish <span class="op">=</span> common_range<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">||</span> <span class="op">(</span>random_accessed_range<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> sized_range<span class="op">&lt;</span>R<span class="op">&gt;)</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>concat<span class="op">-</span>is<span class="op">-</span>bidi <span class="op">=</span> <span class="op">(</span>bidirectional_range<span class="op">&lt;</span>all<span class="op">-</span>views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">&amp;&amp;</span> <span class="op">(</span>common<span class="op">-</span>ish<span class="op">&lt;</span>all<span class="op">-</span>but<span class="op">-</span>last<span class="op">-</span>views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span></code></pre></div>
<p>In the LWG wording review on 2023-09-13, it was suggested that
<code class="sourceCode default">concat_view</code>’s
<code class="sourceCode default">bidirectional_range</code> behaviour
should be consistent with its
<code class="sourceCode default">common_range</code> behaviour, i.e, do
not support <code class="sourceCode default">!common_range &amp;&amp; random_accessed_range &amp;&amp; sized_range</code>
ranges. This would simplify the wording, so that to get to the end of
the previous range,
<code class="sourceCode default">--ranges::end(r)</code> would always
work.</p>
<p>So,</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>concat<span class="op">-</span>is<span class="op">-</span>bidi <span class="op">=</span> <span class="op">(</span>bidirectional_range<span class="op">&lt;</span>all<span class="op">-</span>views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">&amp;&amp;</span> <span class="op">(</span>common_range<span class="op">&lt;</span>all<span class="op">-</span>but<span class="op">-</span>last<span class="op">-</span>views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span></code></pre></div>
<p>Similarly,
<code class="sourceCode default">random_access_range</code> could follow
the same design. To implement
<code class="sourceCode default">it + n</code>, it is necessary to know
if <code class="sourceCode default">n</code> is larger than the distance
from <code class="sourceCode default">it</code> to the end of the
current underlying range. If the underlying range is <code class="sourceCode default">!common_range &amp;&amp; random_accessed_range &amp;&amp; sized_range</code>,
to compute the distance from <code class="sourceCode default">it</code>
to the end of the range, an implementation must do <code class="sourceCode default">ranges::size(r) - (it - ranges::begin(r))</code>.
If it is <code class="sourceCode default">common_range</code>, the
distance is simply <code class="sourceCode default">ranges::distance(it, ranges::end(r))</code>.</p>
<p>If the support of <code class="sourceCode default">!common_range &amp;&amp; random_accessed_range &amp;&amp; sized_range</code>
is dropped, it would simplify the exposition only helper functions
<code class="sourceCode default">advance_fwd</code>,
<code class="sourceCode default">advance_bwd</code> and all other random
access related functions.</p>
<p>So change</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>concat<span class="op">-</span>is<span class="op">-</span>random<span class="op">-</span>access <span class="op">=</span> <span class="op">(</span>random_access_range<span class="op">&lt;</span>all<span class="op">-</span>views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">&amp;&amp;</span> <span class="op">(</span>sized_range<span class="op">&lt;</span>all<span class="op">-</span>but<span class="op">-</span>last<span class="op">-</span>views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span></code></pre></div>
<p>to</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>concat<span class="op">-</span>is<span class="op">-</span>random<span class="op">-</span>access <span class="op">=</span> <span class="op">(</span>random_access_range<span class="op">&lt;</span>all<span class="op">-</span>views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">&amp;&amp;</span> <span class="op">(</span>common_range<span class="op">&lt;</span>all<span class="op">-</span>but<span class="op">-</span>last<span class="op">-</span>views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span></code></pre></div>
<p>Ranges that are <code class="sourceCode default">!common_range &amp;&amp; random_accessed_range &amp;&amp; sized_range</code>
are rare, and if the user does have one of these ranges and would like
to have common, bidirectional or random access support in the
<code class="sourceCode default">concat_view</code>, they can do</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">auto</span> cv <span class="op">=</span> views<span class="op">::</span>concat<span class="op">(</span>r <span class="op">|</span> views<span class="op">::</span>common, other_views<span class="op">...)</span></span></code></pre></div>
<p>As per LEWG direction, the change proposed in this section is adopted
## Bidirectional Range</p>
<p><code class="sourceCode default">concat_view</code> can model
<code class="sourceCode default">bidirectional_range</code> if the
underlying ranges satisfy the following conditions:</p>
<ul>
<li>Every underlying range models
<code class="sourceCode default">bidirectional_range</code><br />
</li>
<li>If the iterator is at nth range’s begin position, after
<code class="sourceCode default">operator--</code> it should go to
(n-1)th’s range’s end-1 position. This means, the (n-1)th range has to
support either
<ul>
<li><code class="sourceCode default">common_range &amp;&amp; bidirectional_range</code>,
so the position can be reached by
<code class="sourceCode default">--ranges::end(n-1th range)</code>,
assuming n-1th range is not empty, or</li>
<li><code class="sourceCode default">random_access_range &amp;&amp; sized_range</code>,
so the position can be reached by <code class="sourceCode default">ranges::begin(n-1th range) + (ranges::size(n-1th range) - 1)</code>
in constant time, assuming n-1th range is not empty. However, as per
LEWG’s direction,<code class="sourceCode default">!common_range &amp;&amp; random_access_range &amp;&amp; sized_range</code>
is removed</li>
</ul>
Note that the last underlying range does not have to satisfy this
constraint because n-1 can never be the last underlying range. If
neither of the two constraints is satisfied, in theory we can cache the
end-1 position for every single underlying range inside the
<code class="sourceCode default">concat_view</code> itself. But the
authors do not consider this type of ranges as worth supporting
bidirectional</li>
</ul>
<p>In the <code class="sourceCode default">concat</code> implementation
in <span class="citation" data-cites="rangev3">[<a href="#ref-rangev3" role="doc-biblioref">range-v3</a>]</span>,
<code class="sourceCode default">operator--</code> is only constrained
on all underlying ranges being
<code class="sourceCode default">bidirectional_range</code> on the
declaration, but its implementation is using <code class="sourceCode default">ranges::next(ranges::begin(r), ranges::end(r))</code>
which implicitly requires random access to make the operation constant
time. So it went with the second constraint.</p>
<h2 data-number="4.6" id="random-access-range"><span class="header-section-number">4.6</span> Random Access Range<a href="#random-access-range" class="self-link"></a></h2>
<p><code class="sourceCode default">concat_view</code> can model
<code class="sourceCode default">random_access_range</code> if the
underlying ranges satisfy the following conditions:</p>
<ul>
<li>Every underlying range models
<code class="sourceCode default">random_access_range</code><br />
</li>
<li>All except the last range model
<code class="sourceCode default">common_range</code></li>
</ul>
<h2 data-number="4.7" id="sized-range"><span class="header-section-number">4.7</span> Sized Range<a href="#sized-range" class="self-link"></a></h2>
<p><code class="sourceCode default">concat_view</code> can be
<code class="sourceCode default">sized_range</code> if all the
underlying ranges model
<code class="sourceCode default">sized_range</code></p>
<h2 data-number="4.8" id="iter_swap-customizations"><span class="header-section-number">4.8</span>
<code class="sourceCode default">iter_swap</code> Customizations<a href="#iter_swap-customizations" class="self-link"></a></h2>
<h3 data-number="4.8.1" id="option-1-delegate-to-the-underlying-iter_swap"><span class="header-section-number">4.8.1</span> Option 1: Delegate to the
Underlying <code class="sourceCode default">iter_swap</code><a href="#option-1-delegate-to-the-underlying-iter_swap" class="self-link"></a></h3>
<p>This option was originally adopted in the paper. If all the
combinations of the underlying iterators model
<code class="sourceCode default">indirectly_swappable</code>, then
<code class="sourceCode default">ranges::iter_swap(x, y)</code> could
delegate to the underlying iterators</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>std<span class="op">::</span>visit<span class="op">(</span>ranges<span class="op">::</span>iter_swap, x<span class="op">.</span>it_, y<span class="op">.</span>it_<span class="op">)</span>;</span></code></pre></div>
<p>This would allow swapping elements across heterogeneous ranges, which
is very powerful. However,
<code class="sourceCode default">ranges::iter_swap</code> is too
permissive. Consider the following example:</p>
<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="dt">int</span> v1<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">}</span>;</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="dt">long</span> v2<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="dv">2147483649</span>, <span class="dv">4</span><span class="op">}</span>;</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> cv <span class="op">=</span> std<span class="op">::</span>views<span class="op">::</span>concat<span class="op">(</span>v1, v2<span class="op">)</span>;</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> it1 <span class="op">=</span> cv<span class="op">.</span>begin<span class="op">()</span>;</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> it2 <span class="op">=</span> cv<span class="op">.</span>begin<span class="op">()</span> <span class="op">+</span> <span class="dv">2</span>;</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>ranges<span class="op">::</span>iter_swap<span class="op">(</span>it1, it2<span class="op">)</span>;</span></code></pre></div>
<p>Delegating <code class="sourceCode default">ranges::iter_swap(const concat_view::iterator&amp;, const concat_view::iterator&amp;)</code>
to
<code class="sourceCode default">ranges::iter_swap(int*, long*)</code>
in this case would result in a tripple-move and leave
<code class="sourceCode default">v1[0]</code> overflowed.</p>
<p>Another example discussed in SG9 mailing list is</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>std<span class="op">::</span>string_view v1<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="st">&quot;aa&quot;</span><span class="op">}</span>;</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>string v2<span class="op">[]</span> <span class="op">=</span> <span class="op">{</span><span class="st">&quot;bbb&quot;</span><span class="op">}</span>;</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> cv <span class="op">=</span> std<span class="op">::</span>views<span class="op">::</span>concat<span class="op">(</span>v1, v2<span class="op">)</span>;</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> it1 <span class="op">=</span> cv<span class="op">.</span>begin<span class="op">()</span>;</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> it2 <span class="op">=</span> cv<span class="op">.</span>begin<span class="op">()+</span><span class="dv">1</span>;</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>ranges<span class="op">::</span>iter_swap<span class="op">(</span>it1, it2<span class="op">)</span>;</span></code></pre></div>
<p><code class="sourceCode default">ranges::iter_swap(string_view*, string*)</code>
in this case would result in dangling reference due to the tripple move,
which is effectively</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="dt">void</span> iter_swap_impl<span class="op">(</span>string_view<span class="op">*</span> x, string<span class="op">*</span> y<span class="op">)</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>string tmp<span class="op">(</span>std<span class="op">::</span>move<span class="op">(*</span>y<span class="op">))</span>;</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">*</span>y <span class="op">=</span> std<span class="op">::</span>move<span class="op">(*</span>x<span class="op">)</span>;</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">*</span>x <span class="op">=</span> std<span class="op">::</span>move<span class="op">(</span>tmp<span class="op">)</span>; <span class="co">// *x points to local string tmp</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>It turned out that allowing swapping elements across heterogeneous
ranges could result in lots of undesired behaviours.</p>
<h3 data-number="4.8.2" id="option-2-do-not-provide-the-customization"><span class="header-section-number">4.8.2</span> Option 2: Do not Provide the
Customization<a href="#option-2-do-not-provide-the-customization" class="self-link"></a></h3>
<p>If the <code class="sourceCode default">iter_swap</code>
customization is removed, the above examples are no longer an issue
because <code class="sourceCode default">ranges::iter_swap</code> would
be ill-formed. This is because <code class="sourceCode default">iter_reference_t&lt;concat_view::iterator&gt;</code>
are prvalues in those cases.</p>
<p>For the trivial cases where underlying ranges share the same
<code class="sourceCode default">iter_reference_t</code>,
<code class="sourceCode default">iter_value_t</code> and
<code class="sourceCode default">iter_rvalue_reference_t</code>, the
genereated tripple-move swap would just work.</p>
<p>However, all the user
<code class="sourceCode default">iter_swap</code> customizations will be
ignored, even if the user tries to
<code class="sourceCode default">concat</code> the same type of ranges
with <code class="sourceCode default">iter_swap</code>
customizations.</p>
<h3 data-number="4.8.3" id="option-3-delegate-to-the-underlying-iter_swap-only-if-they-have-the-same-type"><span class="header-section-number">4.8.3</span> Option 3: Delegate to the
Underlying <code class="sourceCode default">iter_swap</code> Only If
They Have the Same Type<a href="#option-3-delegate-to-the-underlying-iter_swap-only-if-they-have-the-same-type" class="self-link"></a></h3>
<p>This option was suggested by Tomasz in the SG9 mailing list. The idea
is to</p>
<ul>
<li><ol type="1">
<li>use
<code class="sourceCode default">ranges::iter_swap(x.it_, y.it_)</code>
if they have the same underlying iterator type</li>
</ol></li>
<li><ol start="2" type="1">
<li>otherwise,
<code class="sourceCode default">ranges::swap(*x, *y)</code> if it is
valid</li>
</ol></li>
</ul>
<p>The issues decribed in Option 1 are avoided because we only delegate
to underlying <code class="sourceCode default">iter_swap</code> if they
have the same underlying iterators.</p>
<p>The authors believe that this apporach is a good compromise thus it
is adopted in this revision.</p>
<h2 data-number="4.9" id="implementation-experience"><span class="header-section-number">4.9</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h2>
<p><code class="sourceCode default">views::concat</code> has been
implemented in <span class="citation" data-cites="rangev3">[<a href="#ref-rangev3" 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="#ref-ours" role="doc-biblioref">ours</a>]</span>.</p>
<h1 data-number="5" id="wording"><span class="header-section-number">5</span> Wording<a href="#wording" class="self-link"></a></h1>
<h2 data-number="5.1" id="addition-to-ranges"><span class="header-section-number">5.1</span> Addition to
<code class="sourceCode default">&lt;ranges&gt;</code><a href="#addition-to-ranges" class="self-link"></a></h2>
<p>Add the following to <span>26.2
<a href="https://wg21.link/ranges.syn">[ranges.syn]</a></span>, header
<code class="sourceCode default">&lt;ranges&gt;</code> synopsis:</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><span class="co">// [...]</span></span>
<span id="cb20-2"><a href="#cb20-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="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [...]</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [range.concat], concat view</span></span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>input_range<span class="op">...</span> Views<span class="op">&gt;</span></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>see below</em></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> concat_view;</span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">namespace</span> views <span class="op">{</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">inline</span> <span class="kw">constexpr</span> <em>unspecified</em> concat <span class="op">=</span> <em>unspecified</em>;</span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="5.2" id="move-exposition-only-utilities"><span class="header-section-number">5.2</span> Move exposition-only
utilities<a href="#move-exposition-only-utilities" class="self-link"></a></h2>
<p>Move
<code class="sourceCode default"><em>all-random-access</em></code>,
<code class="sourceCode default"><em>all-bidirectional</em></code>, and
<code class="sourceCode default"><em>all-forward</em></code> from
<span>26.7.24.3
<a href="https://wg21.link/range.zip.iterator">[range.zip.iterator]</a></span>
to <span>26.7.5
<a href="https://wg21.link/range.adaptor.helpers">[range.adaptor.helpers]</a></span>.</p>
<p>Add the following to <span>26.7.5
<a href="https://wg21.link/range.adaptor.helpers">[range.adaptor.helpers]</a></span></p>
<div>
<div class="sourceCode" id="cb21"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>namespace std::ranges {</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>// [...]</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;bool Const, class... Views&gt;</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a><span class="va">+   concept <em>all-random-access</em> =                 // exposition only</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a><span class="va">+     (random_access_range&lt;<em>maybe-const</em>&lt;Const, Views&gt;&gt; &amp;&amp; ...);</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;bool Const, class... Views&gt;</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a><span class="va">+   concept <em>all-bidirectional</em> =                 // exposition only</span></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a><span class="va">+     (bidirectional_range&lt;<em>maybe-const</em>&lt;Const, Views&gt;&gt; &amp;&amp; ...);</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a><span class="va">+ template&lt;bool Const, class... Views&gt;</span></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a><span class="va">+   concept <em>all-forward</em> =                       // exposition only</span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a><span class="va">+     (forward_range&lt;<em>maybe-const</em>&lt;Const, Views&gt;&gt; &amp;&amp; ...);</span></span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>// [...]</span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</div>
<p>Remove the following from <span>26.7.24.3
<a href="https://wg21.link/range.zip.iterator">[range.zip.iterator]</a></span></p>
<div>
<div class="sourceCode" id="cb22"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>namespace std::ranges {</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="st">- template&lt;bool Const, class... Views&gt;</span></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="st">-   concept <em>all-random-access</em> =                 // exposition only</span></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="st">-     (random_access_range&lt;<em>maybe-const</em>&lt;Const, Views&gt;&gt; &amp;&amp; ...);</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a><span class="st">- template&lt;bool Const, class... Views&gt;</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a><span class="st">-   concept <em>all-bidirectional</em> =                 // exposition only</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a><span class="st">-     (bidirectional_range&lt;<em>maybe-const</em>&lt;Const, Views&gt;&gt; &amp;&amp; ...);</span></span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a><span class="st">- template&lt;bool Const, class... Views&gt;</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="st">-   concept <em>all-forward</em> =                       // exposition only</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a><span class="st">-     (forward_range&lt;<em>maybe-const</em>&lt;Const, Views&gt;&gt; &amp;&amp; ...);</span></span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>// [...]</span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</div>
<h2 data-number="5.3" id="concat"><span class="header-section-number">5.3</span>
<code class="sourceCode default">concat</code><a href="#concat" class="self-link"></a></h2>
<p>Add the following subclause to <span>26.7
<a href="https://wg21.link/range.adaptors">[range.adaptors]</a></span>.</p>
<h3 class="unnumbered" id="concat-view-range.concat">?.?.? Concat view
[range.concat]<a href="#concat-view-range.concat" class="self-link"></a></h3>
<h4 class="unnumbered" id="overview-range.concat.overview">?.?.?.1
Overview [range.concat.overview]<a href="#overview-range.concat.overview" class="self-link"></a></h4>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<code class="sourceCode default">concat_view</code> presents a
<code class="sourceCode default">view</code> that concatenates all the
underlying ranges.</p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
The name <code class="sourceCode default">views::concat</code> denotes a
customization point object (<span>16.3.3.3.5
<a href="https://wg21.link/customization.point.object">[customization.point.object]</a></span>).
Given a pack of subexpressions
<code class="sourceCode default">Es...</code>, the expression
<code class="sourceCode default">views::concat(Es...)</code> is
expression-equivalent to</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(2.1)</a></span>
<code class="sourceCode default">views::all(Es...)</code> if
<code class="sourceCode default">Es</code> is a pack with only one
element,</li>
<li><span class="marginalizedparent"><a class="marginalized">(2.2)</a></span>
otherwise,
<code class="sourceCode default">concat_view(Es...)</code></li>
</ul>
<p>[<em>Example:</em></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<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> v1<span class="op">{</span><span class="dv">1</span>,<span class="dv">2</span>,<span class="dv">3</span><span class="op">}</span>, v2<span class="op">{</span><span class="dv">4</span>,<span class="dv">5</span><span class="op">}</span>, v3<span class="op">{}</span>;</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>array  a<span class="op">{</span><span class="dv">6</span>,<span class="dv">7</span>,<span class="dv">8</span><span class="op">}</span>;</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> s <span class="op">=</span> std<span class="op">::</span>views<span class="op">::</span>single<span class="op">(</span><span class="dv">9</span><span class="op">)</span>;</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span><span class="op">(</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> i <span class="op">:</span> std<span class="op">::</span>views<span class="op">::</span>concat<span class="op">(</span>v1, v2, v3, a, s<span class="op">)){</span></span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>print<span class="op">(</span><span class="st">&quot;{} &quot;</span>, i<span class="op">)</span>; <span class="co">// prints: 1 2 3 4 5 6 7 8 9 </span></span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<ul>
<li><em>end example</em>]</li>
</ul>
<h4 class="unnumbered" id="class-template-concat_view-range.concat.view">?.?.?.2 Class template
<code class="sourceCode default">concat_view</code>
[range.concat.view]<a href="#class-template-concat_view-range.concat.view" class="self-link"></a></h4>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-3"><a href="#cb24-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">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <em>concat-reference-t</em> <span class="op">=</span> common_reference_t<span class="op">&lt;</span>range_reference_t<span class="op">&lt;</span>Rs<span class="op">&gt;...&gt;</span>; <span class="co">// exposition only</span></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-6"><a href="#cb24-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">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <em>concat-value-t</em> <span class="op">=</span> common_type_t<span class="op">&lt;</span>range_value_t<span class="op">&lt;</span>Rs<span class="op">&gt;...&gt;</span>; <span class="co">// exposition only</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> <em>concat-rvalue-reference-t</em> <span class="op">=</span> common_reference_t<span class="op">&lt;</span>range_rvalue_reference_t<span class="op">&lt;</span>Rs<span class="op">&gt;...&gt;</span>; <span class="co">// exposition only</span></span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em>concat-indirectly-readable</em> <span class="op">=</span> <em>see below</em>; <span class="co">// exposition only</span></span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em>concatable</em> <span class="op">=</span> <em>see below</em>;             <span class="co">// exposition only</span></span>
<span id="cb24-17"><a href="#cb24-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-18"><a href="#cb24-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> Const, <span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb24-19"><a href="#cb24-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em>concat-is-random-access</em> <span class="op">=</span> <em>see below</em>;   <span class="co">// exposition only</span></span>
<span id="cb24-20"><a href="#cb24-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-21"><a href="#cb24-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> Const, <span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb24-22"><a href="#cb24-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em>concat-is-bidirectional</em> <span class="op">=</span> <em>see below</em>;   <span class="co">// exposition only</span></span>
<span id="cb24-23"><a href="#cb24-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-24"><a href="#cb24-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>input_range<span class="op">...</span> Views<span class="op">&gt;</span></span>
<span id="cb24-25"><a href="#cb24-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span>view<span class="op">&lt;</span>Views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">&amp;&amp;</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>Views<span class="op">)</span> <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb24-26"><a href="#cb24-26" aria-hidden="true" tabindex="-1"></a>              <em>concatable</em><span class="op">&lt;</span>Views<span class="op">...&gt;</span></span>
<span id="cb24-27"><a href="#cb24-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> concat_view <span class="op">:</span> <span class="kw">public</span> view_interface<span class="op">&lt;</span>concat_view<span class="op">&lt;</span>Views<span class="op">...&gt;&gt;</span> <span class="op">{</span></span>
<span id="cb24-28"><a href="#cb24-28" aria-hidden="true" tabindex="-1"></a>    tuple<span class="op">&lt;</span>Views<span class="op">...&gt;</span> <em>views_</em>;                   <span class="co">// exposition only</span></span>
<span id="cb24-29"><a href="#cb24-29" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-30"><a href="#cb24-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> Const<span class="op">&gt;</span></span>
<span id="cb24-31"><a href="#cb24-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> <em>iterator</em>;                           <span class="co">// exposition only</span></span>
<span id="cb24-32"><a href="#cb24-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-33"><a href="#cb24-33" aria-hidden="true" tabindex="-1"></a>  <span class="kw">public</span><span class="op">:</span></span>
<span id="cb24-34"><a href="#cb24-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> concat_view<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb24-35"><a href="#cb24-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-36"><a href="#cb24-36" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">explicit</span> concat_view<span class="op">(</span>Views<span class="op">...</span> views<span class="op">)</span>;</span>
<span id="cb24-37"><a href="#cb24-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-38"><a href="#cb24-38" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>iterator</em><span class="op">&lt;</span><span class="kw">false</span><span class="op">&gt;</span> begin<span class="op">()</span> <span class="kw">requires</span><span class="op">(!(</span><em>simple-view</em><span class="op">&lt;</span>Views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...))</span>;</span>
<span id="cb24-39"><a href="#cb24-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-40"><a href="#cb24-40" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>iterator</em><span class="op">&lt;</span><span class="kw">true</span><span class="op">&gt;</span> begin<span class="op">()</span> <span class="kw">const</span></span>
<span id="cb24-41"><a href="#cb24-41" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span><span class="op">((</span>range<span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">&amp;&amp;</span> <em>concatable</em><span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">...&gt;)</span>;</span>
<span id="cb24-42"><a href="#cb24-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-43"><a href="#cb24-43" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> end<span class="op">()</span> <span class="kw">requires</span><span class="op">(!(</span><em>simple-view</em><span class="op">&lt;</span>Views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...))</span>;</span>
<span id="cb24-44"><a href="#cb24-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-45"><a href="#cb24-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> end<span class="op">()</span> <span class="kw">const</span></span>
<span id="cb24-46"><a href="#cb24-46" aria-hidden="true" tabindex="-1"></a>      <span class="kw">requires</span><span class="op">((</span>range<span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">&amp;&amp;</span> <em>concatable</em><span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">...&gt;)</span>;</span>
<span id="cb24-47"><a href="#cb24-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-48"><a href="#cb24-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">requires</span><span class="op">(</span>sized_range<span class="op">&lt;</span>Views<span class="op">&gt;&amp;&amp;...)</span>;</span>
<span id="cb24-49"><a href="#cb24-49" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-50"><a href="#cb24-50" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span><span class="op">(</span>sized_range<span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">&gt;&amp;&amp;...)</span>;</span>
<span id="cb24-51"><a href="#cb24-51" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb24-52"><a href="#cb24-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-53"><a href="#cb24-53" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> R<span class="op">&gt;</span></span>
<span id="cb24-54"><a href="#cb24-54" aria-hidden="true" tabindex="-1"></a>    concat_view<span class="op">(</span>R<span class="op">&amp;&amp;...)</span> <span class="op">-&gt;</span> concat_view<span class="op">&lt;</span>views<span class="op">::</span>all_t<span class="op">&lt;</span>R<span class="op">&gt;...&gt;</span>;</span>
<span id="cb24-55"><a href="#cb24-55" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> <em>concat-indirectly-readable</em> <span class="op">=</span> <em>see below</em>; <span class="co">// exposition only</span></span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<span id="concat-indirectly-readable-definition"></span> The
exposition-only
<code class="sourceCode default"><em>concat-indirectly-readable</em></code>
concept is equivalent to:</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><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Ref, <span class="kw">class</span> RRef, <span class="kw">class</span> It<span class="op">&gt;</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> <em>concat-indirectly-readable-impl</em> <span class="op">=</span>  <span class="co">// exposition only</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="kw">requires</span> <span class="op">(</span><span class="kw">const</span> It it<span class="op">)</span> <span class="op">{</span> </span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span> <span class="op">*</span>it <span class="op">}</span> <span class="op">-&gt;</span> convertible_to<span class="op">&lt;</span>Ref<span class="op">&gt;</span>;</span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span> ranges<span class="op">::</span>iter_move<span class="op">(</span>it<span class="op">)</span> <span class="op">}</span> <span class="op">-&gt;</span> convertible_to<span class="op">&lt;</span>RRef<span class="op">&gt;</span>;</span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> <em>concat-indirectly-readable</em> <span class="op">=</span> <span class="co">// exposition only</span></span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a>  common_reference_with<span class="op">&lt;</span><em>concat-reference-t</em><span class="op">&lt;</span>Rs<span class="op">...&gt;&amp;&amp;</span>, </span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a>                        <em>concat-value-t</em><span class="op">&lt;</span>Rs<span class="op">...&gt;&amp;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a>  common_reference_with<span class="op">&lt;</span><em>concat-reference-t</em><span class="op">&lt;</span>Rs<span class="op">...&gt;&amp;&amp;</span>, </span>
<span id="cb26-13"><a href="#cb26-13" aria-hidden="true" tabindex="-1"></a>                        <em>concat-rvalue-reference-t</em><span class="op">&lt;</span>Rs<span class="op">...&gt;&amp;&amp;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a>  common_reference_with<span class="op">&lt;</span><em>concat-rvalue-reference-t</em><span class="op">&lt;</span>Rs<span class="op">...&gt;&amp;&amp;</span>, </span>
<span id="cb26-15"><a href="#cb26-15" aria-hidden="true" tabindex="-1"></a>                        <em>concat-value-t</em><span class="op">&lt;</span>Rs<span class="op">...&gt;</span> <span class="kw">const</span><span class="op">&amp;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb26-16"><a href="#cb26-16" aria-hidden="true" tabindex="-1"></a>  <span class="op">(</span><em>concat-indirectly-readable-impl</em><span class="op">&lt;</span><em>concat-reference-t</em><span class="op">&lt;</span>Rs<span class="op">...&gt;</span>, </span>
<span id="cb26-17"><a href="#cb26-17" aria-hidden="true" tabindex="-1"></a>                                   <em>concat-rvalue-reference-t</em><span class="op">&lt;</span>Rs<span class="op">...&gt;</span>, </span>
<span id="cb26-18"><a href="#cb26-18" aria-hidden="true" tabindex="-1"></a>                                   iterator_t<span class="op">&lt;</span>Rs<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span>;</span></code></pre></div>
</div>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> <em>concatable</em> <span class="op">=</span> <em>see below</em>; <span class="co">// exposition only</span></span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<span id="concatable-definition"></span> The exposition-only
<code class="sourceCode default"><em>concatable</em></code> concept is
equivalent to:</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="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> <em>concatable</em> <span class="op">=</span> <span class="kw">requires</span> <span class="op">{</span> <span class="co">// exposition only</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> <em>concat-reference-t</em><span class="op">&lt;</span>Rs<span class="op">...&gt;</span>;</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> <em>concat-value-t</em><span class="op">&lt;</span>Rs<span class="op">...&gt;</span>;</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> <em>concat-rvalue-reference-t</em><span class="op">&lt;</span>Rs<span class="op">...&gt;</span>;</span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="op">&amp;&amp;</span> <em>concat-indirectly-readable</em><span class="op">&lt;</span>Rs<span class="op">...&gt;</span>;</span></code></pre></div>
</div>
<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="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> Const, <span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> <em>concat-is-random-access</em> <span class="op">=</span> <em>see below</em>; <span class="co">// exposition only</span></span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
Let <code class="sourceCode default">Fs</code> be the pack that consists
of all elements of <code class="sourceCode default">Rs</code> except the
last element, then
<code class="sourceCode default"><em>concat-is-random-access</em></code>
is equivalent to:</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="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> Const, <span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> <em>concat-is-random-access</em> <span class="op">=</span> <span class="co">// exposition only</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>   <em>all-random-access</em><span class="op">&lt;</span>Const, Rs<span class="op">...&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>   <span class="op">(</span>common_range<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Fs<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span>;</span></code></pre></div>
</div>
<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="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> Const, <span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> <em>concat-is-bidirectional</em> <span class="op">=</span> <em>see below</em>; <span class="co">// exposition only</span></span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
Let <code class="sourceCode default">Fs</code> be the pack that consists
of all elements of <code class="sourceCode default">Rs</code> except the
last element, then
<code class="sourceCode default"><em>concat-is-bidirectional</em></code>
is equivalent to:</p>
<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="dt">bool</span> Const, <span class="kw">class</span><span class="op">...</span> Rs<span class="op">&gt;</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a><span class="kw">concept</span> <em>concat-is-bidirectional</em> <span class="op">=</span> <span class="co">// exposition only</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>  <em>all-bidirectional</em><span class="op">&lt;</span>Const, Rs<span class="op">...&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">(</span>common_range<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Fs<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span>;</span></code></pre></div>
</div>
<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">constexpr</span> <span class="kw">explicit</span> concat_view<span class="op">(</span>Views<span class="op">...</span> views<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
<em>Effects</em>: Initializes
<code class="sourceCode default"><em>views_</em></code> with
<code class="sourceCode default">std::move(views)...</code>.</p>
</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> <em>iterator</em><span class="op">&lt;</span><span class="kw">false</span><span class="op">&gt;</span> begin<span class="op">()</span> <span class="kw">requires</span><span class="op">(!(</span><em>simple-view</em><span class="op">&lt;</span>Views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...))</span>;</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <em>iterator</em><span class="op">&lt;</span><span class="kw">true</span><span class="op">&gt;</span> begin<span class="op">()</span> <span class="kw">const</span></span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">((</span>range<span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">&amp;&amp;</span> <em>concatable</em><span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">...&gt;)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
<em>Effects</em>: Let
<code class="sourceCode default"><em>is-const</em></code> be
<code class="sourceCode default">true</code> for the const-qualified
overload, and <code class="sourceCode default">false</code> otherwise.
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><em>iterator</em><span class="op">&lt;</span><em>is-const</em><span class="op">&gt;</span> it<span class="op">(</span><span class="kw">this</span>, in_place_index<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;</span>, ranges<span class="op">::</span>begin<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;(</span><em>views_</em><span class="op">)))</span>;</span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>it<span class="op">.</span><span class="kw">template</span> <em>satisfy</em><span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;()</span>;</span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> it;</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> <span class="kw">auto</span> end<span class="op">()</span> <span class="kw">requires</span><span class="op">(!(</span><em>simple-view</em><span class="op">&lt;</span>Views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...))</span>;</span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> end<span class="op">()</span> <span class="kw">const</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">((</span>range<span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">&amp;&amp;</span> <em>concatable</em><span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">...&gt;)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<em>Effects</em>: Let
<code class="sourceCode default"><em>is-const</em></code> be
<code class="sourceCode default">true</code> for the const-qualified
overload, and <code class="sourceCode default">false</code> otherwise.
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="kw">constexpr</span> <span class="kw">auto</span> N <span class="op">=</span> <span class="kw">sizeof</span><span class="op">...(</span>Views<span class="op">)</span>;</span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>common_range<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span><em>is-const</em>, Views<span class="op">...[</span>N<span class="op">-</span><span class="dv">1</span><span class="op">]&gt;&gt;)</span> <span class="op">{</span></span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <em>iterator</em><span class="op">&lt;</span><em>is-const</em><span class="op">&gt;(</span><span class="kw">this</span>, in_place_index<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;</span>, </span>
<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a>                      ranges<span class="op">::</span>end<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;(</span><em>views_</em><span class="op">)))</span>;</span>
<span id="cb37-5"><a href="#cb37-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb37-6"><a href="#cb37-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> default_sentinel;</span>
<span id="cb37-7"><a href="#cb37-7" aria-hidden="true" tabindex="-1"></a><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="kw">auto</span> size<span class="op">()</span> <span class="kw">requires</span><span class="op">(</span>sized_range<span class="op">&lt;</span>Views<span class="op">&gt;&amp;&amp;...)</span>;</span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span><span class="op">(</span>sized_range<span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">&gt;&amp;&amp;...)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">8</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> apply<span class="op">(</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">[](</span><span class="kw">auto</span><span class="op">...</span> sizes<span class="op">)</span> <span class="op">{</span></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>        <span class="kw">using</span> CT <span class="op">=</span> <em>make-unsigned-like-t</em><span class="op">&lt;</span>common_type_t<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>sizes<span class="op">)...&gt;&gt;</span>;</span>
<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">(</span>CT<span class="op">(</span>sizes<span class="op">)</span> <span class="op">+</span> <span class="op">...)</span>;</span>
<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>,</span>
<span id="cb39-6"><a href="#cb39-6" aria-hidden="true" tabindex="-1"></a>    <em>tuple-transform</em><span class="op">(</span>ranges<span class="op">::</span>size, <em>views_</em><span class="op">))</span>;</span></code></pre></div>
</div>
<h4 class="unnumbered" id="class-concat_viewiterator-range.concat.iterator">?.?.?.3 Class
concat_view::iterator [range.concat.iterator]<a href="#class-concat_viewiterator-range.concat.iterator" 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">namespace</span> std<span class="op">::</span>ranges<span class="op">{</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span>input_range<span class="op">...</span> Views<span class="op">&gt;</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span>view<span class="op">&lt;</span>Views<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span> <span class="op">&amp;&amp;</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>Views<span class="op">)</span> <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>              <em>concatable</em><span class="op">&lt;</span>Views<span class="op">...&gt;</span></span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">bool</span> Const<span class="op">&gt;</span></span>
<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> concat_view<span class="op">&lt;</span>Views<span class="op">...&gt;::</span><em>iterator</em> <span class="op">{</span></span>
<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">public</span><span class="op">:</span></span>
<span id="cb40-10"><a href="#cb40-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="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator_concept <span class="op">=</span> <em>see below</em>;</span>
<span id="cb40-12"><a href="#cb40-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> value_type <span class="op">=</span> <em>concat-value-t</em><span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;...&gt;</span>;</span>
<span id="cb40-13"><a href="#cb40-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> difference_type <span class="op">=</span> common_type_t<span class="op">&lt;</span>range_difference_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;...&gt;</span>;</span>
<span id="cb40-14"><a href="#cb40-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-15"><a href="#cb40-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">private</span><span class="op">:</span></span>
<span id="cb40-16"><a href="#cb40-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> <em>base-iter</em> <span class="op">=</span>                                     <span class="co">// exposition only</span></span>
<span id="cb40-17"><a href="#cb40-17" aria-hidden="true" tabindex="-1"></a>      variant<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;...&gt;</span>;</span>
<span id="cb40-18"><a href="#cb40-18" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb40-19"><a href="#cb40-19" aria-hidden="true" tabindex="-1"></a>    <em>maybe-const</em><span class="op">&lt;</span>Const, concat_view<span class="op">&gt;*</span> <em>parent_</em> <span class="op">=</span> <span class="kw">nullptr</span>;   <span class="co">// exposition only</span></span>
<span id="cb40-20"><a href="#cb40-20" aria-hidden="true" tabindex="-1"></a>    <em>base-iter</em> <em>it_</em>;                                        <span class="co">// exposition only</span></span>
<span id="cb40-21"><a href="#cb40-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-22"><a href="#cb40-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb40-23"><a href="#cb40-23" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">void</span> <em>satisfy</em><span class="op">()</span>;                             <span class="co">// exposition only</span></span>
<span id="cb40-24"><a href="#cb40-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-25"><a href="#cb40-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb40-26"><a href="#cb40-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">void</span> <em>prev</em><span class="op">()</span>;                                <span class="co">// exposition only</span></span>
<span id="cb40-27"><a href="#cb40-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-28"><a href="#cb40-28" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb40-29"><a href="#cb40-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">void</span> <em>advance-fwd</em><span class="op">(</span>difference_type offset, difference_type steps<span class="op">)</span>; <span class="co">// exposition only</span></span>
<span id="cb40-30"><a href="#cb40-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-31"><a href="#cb40-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb40-32"><a href="#cb40-32" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">void</span> <em>advance-bwd</em><span class="op">(</span>difference_type offset, difference_type steps<span class="op">)</span>; <span class="co">// exposition only</span></span>
<span id="cb40-33"><a href="#cb40-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-34"><a href="#cb40-34" aria-hidden="true" tabindex="-1"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb40-35"><a href="#cb40-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> <em>iterator</em><span class="op">(</span><em>maybe-const</em><span class="op">&lt;</span>Const, concat_view<span class="op">&gt;*</span> parent, Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span> </span>
<span id="cb40-36"><a href="#cb40-36" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> constructible_from<span class="op">&lt;</span><em>base-iter</em>, Args<span class="op">&amp;&amp;...&gt;</span>;  <span class="co">// exposition only</span></span>
<span id="cb40-37"><a href="#cb40-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-38"><a href="#cb40-38" aria-hidden="true" tabindex="-1"></a>  <span class="kw">public</span><span class="op">:</span></span>
<span id="cb40-39"><a href="#cb40-39" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-40"><a href="#cb40-40" aria-hidden="true" tabindex="-1"></a>    <em>iterator</em><span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb40-41"><a href="#cb40-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-42"><a href="#cb40-42" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <em>iterator</em><span class="op">(</span><em>iterator</em><span class="op">&lt;!</span>Const<span class="op">&gt;</span> i<span class="op">)</span> </span>
<span id="cb40-43"><a href="#cb40-43" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> Const <span class="op">&amp;&amp;</span> <span class="op">(</span>convertible_to<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span>Views<span class="op">&gt;</span>, iterator_t<span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span>;</span>
<span id="cb40-44"><a href="#cb40-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-45"><a href="#cb40-45" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span>;</span>
<span id="cb40-46"><a href="#cb40-46" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-47"><a href="#cb40-47" 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="cb40-48"><a href="#cb40-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-49"><a href="#cb40-49" 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="cb40-50"><a href="#cb40-50" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-51"><a href="#cb40-51" 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="cb40-52"><a href="#cb40-52" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>all-forward</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-53"><a href="#cb40-53" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb40-54"><a href="#cb40-54" 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="cb40-55"><a href="#cb40-55" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>concat-is-bidirectional</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-56"><a href="#cb40-56" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-57"><a href="#cb40-57" 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="cb40-58"><a href="#cb40-58" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>concat-is-bidirectional</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-59"><a href="#cb40-59" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-60"><a href="#cb40-60" 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="cb40-61"><a href="#cb40-61" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-62"><a href="#cb40-62" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-63"><a href="#cb40-63" 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="cb40-64"><a href="#cb40-64" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-65"><a href="#cb40-65" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-66"><a href="#cb40-66" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="kw">operator</span><span class="op">[](</span>difference_type n<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb40-67"><a href="#cb40-67" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-68"><a href="#cb40-68" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-69"><a href="#cb40-69" 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="cb40-70"><a href="#cb40-70" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span><span class="op">(</span>equality_comparable<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;&gt;&amp;&amp;...)</span>;</span>
<span id="cb40-71"><a href="#cb40-71" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-72"><a href="#cb40-72" 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> it, default_sentinel_t<span class="op">)</span>;</span>
<span id="cb40-73"><a href="#cb40-73" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-74"><a href="#cb40-74" 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="cb40-75"><a href="#cb40-75" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>all-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-76"><a href="#cb40-76" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-77"><a href="#cb40-77" 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="cb40-78"><a href="#cb40-78" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>all-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-79"><a href="#cb40-79" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-80"><a href="#cb40-80" 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="cb40-81"><a href="#cb40-81" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>all-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-82"><a href="#cb40-82" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-83"><a href="#cb40-83" 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="cb40-84"><a href="#cb40-84" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>all-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-85"><a href="#cb40-85" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-86"><a href="#cb40-86" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&lt;=&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="cb40-87"><a href="#cb40-87" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <span class="op">(</span><em>all-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb40-88"><a href="#cb40-88" aria-hidden="true" tabindex="-1"></a>         <span class="op">(</span>three_way_comparable<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...))</span>;</span>
<span id="cb40-89"><a href="#cb40-89" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-90"><a href="#cb40-90" 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><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> it, difference_type n<span class="op">)</span></span>
<span id="cb40-91"><a href="#cb40-91" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-92"><a href="#cb40-92" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-93"><a href="#cb40-93" 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, <span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> it<span class="op">)</span></span>
<span id="cb40-94"><a href="#cb40-94" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-95"><a href="#cb40-95" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-96"><a href="#cb40-96" 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><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> it, difference_type n<span class="op">)</span></span>
<span id="cb40-97"><a href="#cb40-97" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-98"><a href="#cb40-98" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-99"><a href="#cb40-99" 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="cb40-100"><a href="#cb40-100" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb40-101"><a href="#cb40-101" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-102"><a href="#cb40-102" 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, default_sentinel_t<span class="op">)</span> </span>
<span id="cb40-103"><a href="#cb40-103" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>see below</em>;</span>
<span id="cb40-104"><a href="#cb40-104" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-105"><a href="#cb40-105" 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>default_sentinel_t, <span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> x<span class="op">)</span> </span>
<span id="cb40-106"><a href="#cb40-106" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>see below</em>;</span>
<span id="cb40-107"><a href="#cb40-107" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-108"><a href="#cb40-108" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> iter_move<span class="op">(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> it<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span><em>see below</em><span class="op">)</span>;</span>
<span id="cb40-109"><a href="#cb40-109" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-110"><a href="#cb40-110" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">void</span> iter_swap<span class="op">(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> x, <span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> y<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span><em>see below</em><span class="op">)</span></span>
<span id="cb40-111"><a href="#cb40-111" aria-hidden="true" tabindex="-1"></a>        <span class="kw">requires</span> <em>see below</em>;</span>
<span id="cb40-112"><a href="#cb40-112" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span>;</span>
<span id="cb40-113"><a href="#cb40-113" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb40-114"><a href="#cb40-114" 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 default"><em>iterator</em>::iterator_concept</code>
is defined as follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(1.1)</a></span> If
<code class="sourceCode default"><em>concat-is-random-access</em>&lt;Const, Views...&gt;</code>
is modeled, then
<code class="sourceCode default">iterator_concept</code> denotes
<code class="sourceCode default">random_access_iterator_tag</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized">(1.2)</a></span>
Otherwise, if <code class="sourceCode default"><em>concat-is-bidirectional</em>&lt;Const, Views...&gt;</code>
is modeled, then
<code class="sourceCode default">iterator_concept</code> denotes
<code class="sourceCode default">bidirectional_iterator_tag</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized">(1.3)</a></span>
Otherwise, if <code class="sourceCode default"><em>all-forward</em>&lt;Const, Views...&gt;</code>
is modeled, then
<code class="sourceCode default">iterator_concept</code> denotes
<code class="sourceCode default">forward_iterator_tag</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized">(1.4)</a></span>
Otherwise, <code class="sourceCode default">iterator_concept</code>
denotes <code class="sourceCode default">input_iterator_tag</code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
The member typedef-name
<code class="sourceCode default">iterator_category</code> is defined if
and only if <code class="sourceCode default"><em>all-forward</em>&lt;Const, Views...&gt;</code>
is modeled. In that case,
<code class="sourceCode default">iterator::iterator_category</code> is
defined as follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(2.1)</a></span> If
<code class="sourceCode default">is_reference_v&lt;<em>concat-reference-t</em>&lt;<em>maybe-const</em>&lt;Const, Views&gt;...&gt;&gt;</code>
is <code class="sourceCode default">false</code>, then
<code class="sourceCode default">iterator_category</code> denotes
<code class="sourceCode default">input_iterator_tag</code></li>
<li><span class="marginalizedparent"><a class="marginalized">(2.2)</a></span>
Otherwise, let <code class="sourceCode default">Cs</code> denote the
pack of types <code class="sourceCode default">iterator_traits&lt;iterator_t&lt;<em>maybe-const</em>&lt;Const, Views&gt;&gt;&gt;::iterator_category...</code>.
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(2.2.1)</a></span> If
<code class="sourceCode default">(derived_from&lt;Cs, random_access_iterator_tag&gt; &amp;&amp; ...) &amp;&amp; <em>concat-is-random-access</em>&lt;Const, Views...&gt;</code>
is true, <code class="sourceCode default">iterator_category</code>
denotes
<code class="sourceCode default">random_access_iterator_tag</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized">(2.2.2)</a></span>
Otherwise, if <code class="sourceCode default">(derived_from&lt;Cs, bidirectional_iterator_tag&gt; &amp;&amp; ...) &amp;&amp; <em>concat-is-bidirectional</em>&lt;Const, Views...&gt;</code>
is true, <code class="sourceCode default">iterator_category</code>
denotes
<code class="sourceCode default">bidirectional_iterator_tag</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized">(2.2.3)</a></span>
Otherwise, If <code class="sourceCode default">(derived_from&lt;Cs, forward_iterator_tag&gt; &amp;&amp; ...)</code>
is true, <code class="sourceCode default">iterator_category</code>
denotes
<code class="sourceCode default">forward_iterator_tag</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized">(2.2.4)</a></span>
Otherwise, <code class="sourceCode default">iterator_category</code>
denotes <code class="sourceCode default">input_iterator_tag</code>.</li>
</ul></li>
</ul>
<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">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">void</span> <em>satisfy</em><span class="op">()</span>;                             <span class="co">// exposition only</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="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="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>N <span class="op">&lt;</span> <span class="op">(</span><span class="kw">sizeof</span><span class="op">...(</span>Views<span class="op">)</span> <span class="op">-</span> <span class="dv">1</span><span class="op">))</span> <span class="op">{</span></span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>N<span class="op">&gt;(</span><em>it_</em><span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>N<span class="op">&gt;(</span><em>parent_</em><span class="op">-&gt;</span><em>views_</em><span class="op">)))</span> <span class="op">{</span></span>
<span id="cb42-3"><a href="#cb42-3" aria-hidden="true" tabindex="-1"></a>        <em>it_</em><span class="op">.</span><span class="kw">template</span> emplace<span class="op">&lt;</span>N <span class="op">+</span> <span class="dv">1</span><span class="op">&gt;(</span>ranges<span class="op">::</span>begin<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>N <span class="op">+</span> <span class="dv">1</span><span class="op">&gt;(</span><em>parent_</em><span class="op">-&gt;</span><em>views_</em><span class="op">)))</span>;</span>
<span id="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>        <em>satisfy</em><span class="op">&lt;</span>N <span class="op">+</span> <span class="dv">1</span><span class="op">&gt;()</span>;</span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb42-6"><a href="#cb42-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</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">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">void</span> <em>prev</em><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="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="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>N <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">--</span>std<span class="op">::</span>get<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;(</span><em>it_</em><span class="op">)</span>;</span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb44-4"><a href="#cb44-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>N<span class="op">&gt;(</span><em>it_</em><span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>begin<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>N<span class="op">&gt;(</span><em>parent_</em><span class="op">-&gt;</span><em>views_</em><span class="op">)))</span> <span class="op">{</span></span>
<span id="cb44-5"><a href="#cb44-5" aria-hidden="true" tabindex="-1"></a>        <em>it_</em><span class="op">.</span><span class="kw">template</span> emplace<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;(</span>ranges<span class="op">::</span>end<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;(</span><em>parent_</em><span class="op">-&gt;</span><em>views_</em><span class="op">)))</span>;</span>
<span id="cb44-6"><a href="#cb44-6" aria-hidden="true" tabindex="-1"></a>        <em>prev</em><span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;()</span>;</span>
<span id="cb44-7"><a href="#cb44-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb44-8"><a href="#cb44-8" aria-hidden="true" tabindex="-1"></a>        <span class="op">--</span>std<span class="op">::</span>get<span class="op">&lt;</span>N<span class="op">&gt;(</span><em>it_</em><span class="op">)</span>;</span>
<span id="cb44-9"><a href="#cb44-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb44-10"><a href="#cb44-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</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">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">void</span> <em>advance-fwd</em><span class="op">(</span>difference_type offset, difference_type steps<span class="op">)</span>; <span class="co">// exposition only</span></span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
<em>Effects</em>: Equivalent to:</p>
<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">using</span> underlying_diff_type <span class="op">=</span> iter_difference_t<span class="op">&lt;</span>variant_alternative_t<span class="op">&lt;</span>N, <em>base-iter</em><span class="op">&gt;&gt;</span>;</span>
<span id="cb46-2"><a href="#cb46-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>N <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Views<span class="op">)</span> <span class="op">-</span> <span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-3"><a href="#cb46-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>get<span class="op">&lt;</span>N<span class="op">&gt;(</span><em>it_</em><span class="op">)</span> <span class="op">+=</span> <span class="kw">static_cast</span><span class="op">&lt;</span>underlying_diff_type<span class="op">&gt;(</span>steps<span class="op">)</span>;</span>
<span id="cb46-4"><a href="#cb46-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb46-5"><a href="#cb46-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> n_size <span class="op">=</span> ranges<span class="op">::</span>distance<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>N<span class="op">&gt;(</span><em>parent_</em><span class="op">-&gt;</span><em>views_</em><span class="op">))</span>;</span>
<span id="cb46-6"><a href="#cb46-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>offset <span class="op">+</span> steps <span class="op">&lt;</span> n_size<span class="op">)</span> <span class="op">{</span></span>
<span id="cb46-7"><a href="#cb46-7" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>get<span class="op">&lt;</span>N<span class="op">&gt;(</span><em>it_</em><span class="op">)</span> <span class="op">+=</span> <span class="kw">static_cast</span><span class="op">&lt;</span>underlying_diff_type<span class="op">&gt;(</span>steps<span class="op">)</span>;</span>
<span id="cb46-8"><a href="#cb46-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb46-9"><a href="#cb46-9" aria-hidden="true" tabindex="-1"></a>        <em>it_</em><span class="op">.</span><span class="kw">template</span> emplace<span class="op">&lt;</span>N <span class="op">+</span> <span class="dv">1</span><span class="op">&gt;(</span>ranges<span class="op">::</span>begin<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>N <span class="op">+</span> <span class="dv">1</span><span class="op">&gt;(</span><em>parent_</em><span class="op">-&gt;</span><em>views_</em><span class="op">)))</span>;</span>
<span id="cb46-10"><a href="#cb46-10" aria-hidden="true" tabindex="-1"></a>        <em>advance-fwd</em><span class="op">&lt;</span>N <span class="op">+</span> <span class="dv">1</span><span class="op">&gt;(</span><span class="dv">0</span>, offset <span class="op">+</span> steps <span class="op">-</span> n_size<span class="op">)</span>;</span>
<span id="cb46-11"><a href="#cb46-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb46-12"><a href="#cb46-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</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">template</span> <span class="op">&lt;</span><span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">void</span> <em>advance-bwd</em><span class="op">(</span>difference_type offset, difference_type steps<span class="op">)</span>; <span class="co">// exposition only</span></span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
<em>Effects</em>: Equivalent to:</p>
<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">using</span> underlying_diff_type <span class="op">=</span> iter_difference_t<span class="op">&lt;</span>variant_alternative_t<span class="op">&lt;</span>N, <em>base-iter</em><span class="op">&gt;&gt;</span>;</span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>N <span class="op">==</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>get<span class="op">&lt;</span>N<span class="op">&gt;(</span><em>it_</em><span class="op">)</span> <span class="op">-=</span> <span class="kw">static_cast</span><span class="op">&lt;</span>underlying_diff_type<span class="op">&gt;(</span>steps<span class="op">)</span>;</span>
<span id="cb48-4"><a href="#cb48-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb48-5"><a href="#cb48-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>offset <span class="op">&gt;=</span> steps<span class="op">)</span> <span class="op">{</span></span>
<span id="cb48-6"><a href="#cb48-6" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>get<span class="op">&lt;</span>N<span class="op">&gt;(</span><em>it_</em><span class="op">)</span> <span class="op">-=</span> <span class="kw">static_cast</span><span class="op">&lt;</span>underlying_diff_type<span class="op">&gt;(</span>steps<span class="op">)</span>;</span>
<span id="cb48-7"><a href="#cb48-7" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb48-8"><a href="#cb48-8" aria-hidden="true" tabindex="-1"></a>        <span class="kw">auto</span> prev_size <span class="op">=</span> ranges<span class="op">::</span>distance<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;(</span><em>parent_</em><span class="op">-&gt;</span><em>views_</em><span class="op">))</span>;</span>
<span id="cb48-9"><a href="#cb48-9" aria-hidden="true" tabindex="-1"></a>        <em>it_</em><span class="op">.</span><span class="kw">template</span> emplace<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;(</span>ranges<span class="op">::</span>end<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;(</span><em>parent_</em><span class="op">-&gt;</span><em>views_</em><span class="op">)))</span>;</span>
<span id="cb48-10"><a href="#cb48-10" aria-hidden="true" tabindex="-1"></a>        <em>advance-bwd</em><span class="op">&lt;</span>N <span class="op">-</span> <span class="dv">1</span><span class="op">&gt;(</span>prev_size, steps <span class="op">-</span> offset<span class="op">)</span>;</span>
<span id="cb48-11"><a href="#cb48-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb48-12"><a href="#cb48-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</div>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a><span class="kw">explicit</span> <span class="kw">constexpr</span> <em>iterator</em><span class="op">(</span></span>
<span id="cb49-3"><a href="#cb49-3" aria-hidden="true" tabindex="-1"></a>            <em>maybe-const</em><span class="op">&lt;</span>Const, concat_view<span class="op">&gt;*</span> parent,</span>
<span id="cb49-4"><a href="#cb49-4" aria-hidden="true" tabindex="-1"></a>            Args<span class="op">&amp;&amp;...</span> args<span class="op">)</span> </span>
<span id="cb49-5"><a href="#cb49-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> constructible_from<span class="op">&lt;</span><em>base-iter</em>, Args<span class="op">&amp;&amp;...&gt;</span>; <span class="co">// exposition only</span></span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<em>Effects</em>: Initializes
<code class="sourceCode default"><em>parent_</em></code> with
<code class="sourceCode default">parent</code>, and initializes
<code class="sourceCode default"><em>it_</em></code> with <code class="sourceCode default">std::forward&lt;Args&gt;(args)...</code>.</p>
</div>
<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> <em>iterator</em><span class="op">(</span><em>iterator</em><span class="op">&lt;!</span>Const<span class="op">&gt;</span> it<span class="op">)</span> </span>
<span id="cb50-2"><a href="#cb50-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> Const <span class="op">&amp;&amp;</span></span>
<span id="cb50-3"><a href="#cb50-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">(</span>convertible_to<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span>Views<span class="op">&gt;</span>, iterator_t<span class="op">&lt;</span><span class="kw">const</span> Views<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</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>: Initializes
<code class="sourceCode default"><em>parent_</em></code> with
<code class="sourceCode default">it.<em>parent_</em></code>, and let
<code class="sourceCode default"><em>i</em></code> be
<code class="sourceCode default">it.<em>it_</em>.index()</code>,
initializes <code class="sourceCode default"><em>it_</em></code> with
<code class="sourceCode default"><em>base-iter</em>(in_place_index&lt;<em>i</em>&gt;, std::get&lt;<em>i</em>&gt;(std::move(it.<em>it_</em>)))</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">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <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">9</a></span>
<em>Preconditions</em>:
<code class="sourceCode default"><em>it_</em>.valueless_by_exception()</code>
is <code class="sourceCode default">false</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">10</a></span>
<em>Effects</em>: Equivalent to:</p>
<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">using</span> reference <span class="op">=</span> <em>concat-reference-t</em><span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;...&gt;</span>;</span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> std<span class="op">::</span>visit<span class="op">([](</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> it<span class="op">)</span> <span class="op">-&gt;</span> reference <span class="op">{</span> </span>
<span id="cb52-3"><a href="#cb52-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">*</span>it; <span class="op">}</span>, <em>it_</em><span class="op">)</span>;</span></code></pre></div>
</div>
<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">&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>Preconditions</em>:
<code class="sourceCode default"><em>it_</em>.valueless_by_exception()</code>
is <code class="sourceCode default">false</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">12</a></span>
<em>Effects</em>: Let <code class="sourceCode default"><em>i</em></code>
be <code class="sourceCode default"><em>it_</em>.index()</code>.
Equivalent to:</p>
<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="op">++</span>std<span class="op">::</span>get<span class="op">&lt;</span><em>i</em><span class="op">&gt;(</span><em>it_</em><span class="op">)</span>;</span>
<span id="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a><em>satisfy</em><span class="op">&lt;</span><em>i</em><span class="op">&gt;()</span>;</span>
<span id="cb54-3"><a href="#cb54-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span></code></pre></div>
</div>
<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="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">13</a></span>
<em>Effects</em>: Equivalent to:</p>
<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="op">++*</span><span class="kw">this</span>;</span></code></pre></div>
</div>
<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="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="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>all-forward</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</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="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">auto</span> tmp <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a><span class="op">++*</span><span class="kw">this</span>;</span>
<span id="cb58-3"><a href="#cb58-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> tmp;</span></code></pre></div>
</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="op">&amp;</span> <span class="kw">operator</span><span class="op">--()</span> </span>
<span id="cb59-2"><a href="#cb59-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>concat-is-bidirectional</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">15</a></span>
<em>Preconditions</em>:
<code class="sourceCode default"><em>it_</em>.valueless_by_exception()</code>
is <code class="sourceCode default">false</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">16</a></span>
<em>Effects</em>: Let <code class="sourceCode default"><em>i</em></code>
be <code class="sourceCode default"><em>it_</em>.index()</code>.
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><em>prev</em><span class="op">&lt;</span><em>i</em><span class="op">&gt;()</span>;</span>
<span id="cb60-2"><a href="#cb60-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>
</div>
<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><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="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>concat-is-bidirectional</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">17</a></span>
<em>Effects</em>: Equivalent to:</p>
<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">auto</span> tmp <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb62-2"><a href="#cb62-2" aria-hidden="true" tabindex="-1"></a><span class="op">--*</span><span class="kw">this</span>;</span>
<span id="cb62-3"><a href="#cb62-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> tmp;</span></code></pre></div>
</div>
<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="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="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">18</a></span>
<em>Preconditions</em>:
<code class="sourceCode default"><em>it_</em>.valueless_by_exception()</code>
is <code class="sourceCode default">false</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">19</a></span>
<em>Effects</em>: Let <code class="sourceCode default"><em>i</em></code>
be <code class="sourceCode default"><em>it_</em>.index()</code>.
Equivalent to:</p>
<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="cf">if</span><span class="op">(</span>n <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb64-2"><a href="#cb64-2" aria-hidden="true" tabindex="-1"></a>  <em>advance-fwd</em><span class="op">&lt;</span><em>i</em><span class="op">&gt;(</span>std<span class="op">::</span>get<span class="op">&lt;</span><em>i</em><span class="op">&gt;(</span><em>it_</em><span class="op">)</span> <span class="op">-</span> ranges<span class="op">::</span>begin<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span><em>i</em><span class="op">&gt;(</span><em>parent_</em><span class="op">-&gt;</span><em>views_</em><span class="op">))</span>, n<span class="op">)</span>;</span>
<span id="cb64-3"><a href="#cb64-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="cf">if</span> <span class="op">(</span>n <span class="op">&lt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb64-4"><a href="#cb64-4" aria-hidden="true" tabindex="-1"></a>  <em>advance-bwd</em><span class="op">&lt;</span><em>i</em><span class="op">&gt;(</span>std<span class="op">::</span>get<span class="op">&lt;</span><em>i</em><span class="op">&gt;(</span><em>it_</em><span class="op">)</span> <span class="op">-</span> ranges<span class="op">::</span>begin<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span><em>i</em><span class="op">&gt;(</span><em>parent_</em><span class="op">-&gt;</span><em>views_</em><span class="op">))</span>, <span class="op">-</span>n<span class="op">)</span>;</span>
<span id="cb64-5"><a href="#cb64-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb64-6"><a href="#cb64-6" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span></code></pre></div>
</div>
<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">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="cb65-2"><a href="#cb65-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">20</a></span>
<em>Effects</em>: Equivalent to:</p>
<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="op">*</span><span class="kw">this</span> <span class="op">+=</span> <span class="op">-</span>n;</span>
<span id="cb66-2"><a href="#cb66-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>
</div>
<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><span class="kw">constexpr</span> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <span class="kw">operator</span><span class="op">[](</span>difference_type n<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb67-2"><a href="#cb67-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">21</a></span>
<em>Effects</em>: Equivalent to:</p>
<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="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="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">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="cb69-2"><a href="#cb69-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>equality_comparable<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;&gt;&amp;&amp;...)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">22</a></span>
<em>Preconditions</em>: <code class="sourceCode default">x.<em>it_</em>.valueless_by_exception()</code>
and <code class="sourceCode default">y.<em>it_</em>.valueless_by_exception()</code>
are each <code class="sourceCode default">false</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">23</a></span>
<em>Effects</em>: Equivalent to:</p>
<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="cf">return</span> x<span class="op">.</span><em>it_</em> <span class="op">==</span> y<span class="op">.</span><em>it_</em>;</span></code></pre></div>
</div>
<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="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> it, default_sentinel_t<span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">24</a></span>
<em>Preconditions</em>: <code class="sourceCode default">it.<em>it_</em>.valueless_by_exception()</code>
is <code class="sourceCode default">false</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">25</a></span>
<em>Effects</em>: Equivalent to:</p>
<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> <span class="kw">auto</span> last_idx <span class="op">=</span> <span class="kw">sizeof</span><span class="op">...(</span>Views<span class="op">)</span> <span class="op">-</span> <span class="dv">1</span>;</span>
<span id="cb72-2"><a href="#cb72-2" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> it<span class="op">.</span><em>it_</em><span class="op">.</span>index<span class="op">()</span> <span class="op">==</span> last_idx <span class="op">&amp;&amp;</span></span>
<span id="cb72-3"><a href="#cb72-3" aria-hidden="true" tabindex="-1"></a>       std<span class="op">::</span>get<span class="op">&lt;</span>last_idx<span class="op">&gt;(</span>it<span class="op">.</span><em>it_</em><span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>std<span class="op">::</span>get<span class="op">&lt;</span>last_idx<span class="op">&gt;(</span>it<span class="op">.</span><em>parent_</em><span class="op">-&gt;</span><em>views_</em><span class="op">))</span>;</span></code></pre></div>
</div>
<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="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="cb73-2"><a href="#cb73-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>all-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb73-3"><a href="#cb73-3" 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="cb73-4"><a href="#cb73-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>all-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb73-5"><a href="#cb73-5" 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="cb73-6"><a href="#cb73-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>all-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb73-7"><a href="#cb73-7" 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="cb73-8"><a href="#cb73-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>all-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span>
<span id="cb73-9"><a href="#cb73-9" aria-hidden="true" tabindex="-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">&lt;=&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="cb73-10"><a href="#cb73-10" aria-hidden="true" tabindex="-1"></a>   <span class="kw">requires</span> <span class="op">(</span><em>all-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb73-11"><a href="#cb73-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">(</span>three_way_comparable<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...))</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">26</a></span>
<em>Preconditions</em>: <code class="sourceCode default">x.<em>it_</em>.valueless_by_exception()</code>
and <code class="sourceCode default">y.<em>it_</em>.valueless_by_exception()</code>
are each <code class="sourceCode default">false</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">27</a></span> Let
<code class="sourceCode default"><em>op</em></code> be the operator.</p>
<p><span class="marginalizedparent"><a class="marginalized">28</a></span>
<em>Effects</em>: Equivalent to:</p>
<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="cf">return</span> x<span class="op">.</span><em>it_</em> <em>op</em> y<span class="op">.</span><em>it_</em>;</span></code></pre></div>
</div>
<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="kw">friend</span> <span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">+(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> it, difference_type n<span class="op">)</span></span>
<span id="cb75-2"><a href="#cb75-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">29</a></span>
<em>Effects</em>: Equivalent to:</p>
<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="kw">auto</span> temp <span class="op">=</span> it;</span>
<span id="cb76-2"><a href="#cb76-2" aria-hidden="true" tabindex="-1"></a>temp <span class="op">+=</span> n;</span>
<span id="cb76-3"><a href="#cb76-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> temp;</span></code></pre></div>
</div>
<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="kw">friend</span> <span class="kw">constexpr</span> <em>iterator</em> <span class="kw">operator</span><span class="op">+(</span>difference_type n, <span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> it<span class="op">)</span></span>
<span id="cb77-2"><a href="#cb77-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">30</a></span>
<em>Effects</em>: 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> it <span class="op">+</span> n;</span></code></pre></div>
</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> <em>iterator</em> <span class="kw">operator</span><span class="op">-(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> it, difference_type n<span class="op">)</span></span>
<span id="cb79-2"><a href="#cb79-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">31</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="kw">auto</span> temp <span class="op">=</span> it;</span>
<span id="cb80-2"><a href="#cb80-2" aria-hidden="true" tabindex="-1"></a>temp <span class="op">-=</span> n;</span>
<span id="cb80-3"><a href="#cb80-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> temp;</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> 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="cb81-2"><a href="#cb81-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>concat-is-random-access</em><span class="op">&lt;</span>Const, Views<span class="op">...&gt;</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">32</a></span>
<em>Preconditions</em>: <code class="sourceCode default">x.<em>it_</em>.valueless_by_exception()</code>
and <code class="sourceCode default">y.<em>it_</em>.valueless_by_exception()</code>
are each <code class="sourceCode default">false</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">33</a></span>
<em>Effects</em>: Let
<code class="sourceCode default"><em>i<sub>x</sub></em></code> denote
<code class="sourceCode default">x.<em>it_</em>.index()</code> and
<code class="sourceCode default"><em>i<sub>y</sub></em></code> denote
<code class="sourceCode default">y.<em>it_</em>.index()</code></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(33.1)</a></span> if
<code class="sourceCode default"><em>i<sub>x</sub></em> &gt; <em>i<sub>y</sub></em></code>,
let <code class="sourceCode default"><em>d<sub>y</sub></em></code> be
<code class="sourceCode default">ranges::distance(std::get&lt;<em>i<sub>y</sub></em>&gt;(y.<em>it_</em>), ranges::end(std::get&lt;<em>i<sub>y</sub></em>&gt;(y.<em>parent_</em>-&gt;<em>views_</em>)))</code>,
<code class="sourceCode default"><em>d<sub>x</sub></em></code> be <code class="sourceCode default">ranges::distance(ranges::begin(std::get&lt;<em>i<sub>x</sub></em>&gt;(x.<em>parent_</em>-&gt;<em>views_</em>)), std::get&lt;<em>i<sub>x</sub></em>&gt;(x.<em>it_</em>))</code>.
Let <code class="sourceCode default">s</code> denote the sum of the
sizes of all the ranges <code class="sourceCode default">std::get&lt;<em>i</em>&gt;(x.<em>parent_</em>-&gt;<em>views_</em>)</code>
for every integer <code class="sourceCode default"><em>i</em></code> in
the range
<code class="sourceCode default">[<em>i<sub>y</sub></em> + 1, <em>i<sub>x</sub></em>)</code>
if there is any, and <code class="sourceCode default">0</code>
otherwise, of type
<code class="sourceCode default">difference_type</code>, 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> <em>d<sub>y</sub></em> <span class="op">+</span> s <span class="op">+</span> <em>d<sub>x</sub></em>;</span></code></pre></div></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(33.2)</a></span>
otherwise, if
<code class="sourceCode default"><em>i<sub>x</sub></em> &lt; <em>i<sub>y</sub></em></code>,
equivalent to:</p>
<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="cf">return</span> <span class="op">-(</span>y <span class="op">-</span> x<span class="op">)</span>;</span></code></pre></div></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(33.3)</a></span>
otherwise, 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> std<span class="op">::</span>get<span class="op">&lt;</span><em>i<sub>x</sub></em><span class="op">&gt;(</span>x<span class="op">.</span><em>it_</em><span class="op">)</span> <span class="op">-</span> std<span class="op">::</span>get<span class="op">&lt;</span><em>i<sub>y</sub></em><span class="op">&gt;(</span>y<span class="op">.</span><em>it_</em><span class="op">)</span>;</span></code></pre></div></li>
</ul>
</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> 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, default_sentinel_t<span class="op">)</span> </span>
<span id="cb85-2"><a href="#cb85-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>see below</em>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">34</a></span>
<em>Preconditions</em>: <code class="sourceCode default">x.<em>it_</em>.valueless_by_exception()</code>
is <code class="sourceCode default">false</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">35</a></span>
<em>Effects</em>: Let
<code class="sourceCode default"><em>i<sub>x</sub></em></code> denote
<code class="sourceCode default">x.<em>it_</em>.index()</code>,
<code class="sourceCode default"><em>d<sub>x</sub></em></code> be <code class="sourceCode default">ranges::distance(std::get&lt;<em>i<sub>x</sub></em>&gt;(x.<em>it_</em>), ranges::end(std::get&lt;<em>i<sub>x</sub></em>&gt;(x.<em>parent_</em>-&gt;<em>views_</em>)))</code>.
Let <code class="sourceCode default">s</code> denote the sum of the
sizes of all the ranges <code class="sourceCode default">std::get&lt;<em>i</em>&gt;(x.<em>parent_</em>-&gt;<em>views_</em>)</code>
for every integer <code class="sourceCode default"><em>i</em></code> in
the range
<code class="sourceCode default">[<em>i<sub>x</sub></em> + 1, sizeof...(Views))</code>
if there is any, and <code class="sourceCode default">0</code>
otherwise, of type
<code class="sourceCode default">difference_type</code>, 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><em>d<sub>x</sub></em> <span class="op">+</span> s<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">36</a></span>
<em>Remarks</em>: Let <code class="sourceCode default">Fs</code> be the
pack that consists of all elements of
<code class="sourceCode default">Views</code> except the first element,
the expression in the requires-clause is equivalent to:</p>
<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="op">(</span>sized_sentinel_for<span class="op">&lt;</span>sentinel_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;</span>, </span>
<span id="cb87-2"><a href="#cb87-2" aria-hidden="true" tabindex="-1"></a>                    iterator_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb87-3"><a href="#cb87-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">&amp;&amp;</span> <span class="op">(</span>sized_range<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Fs<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span></code></pre></div>
</div>
<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">friend</span> <span class="kw">constexpr</span> difference_type <span class="kw">operator</span><span class="op">-(</span>default_sentinel_t, <span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> x<span class="op">)</span> </span>
<span id="cb88-2"><a href="#cb88-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>see below</em>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">37</a></span>
<em>Effects</em>: Equivalent to:</p>
<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="cf">return</span> <span class="op">-(</span>x <span class="op">-</span> default_sentinel<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">38</a></span>
<em>Remarks</em>: Let <code class="sourceCode default">Fs</code> be the
pack that consists of all elements of
<code class="sourceCode default">Views</code> except the first element,
the expression in the requires-clause is 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="op">(</span>sized_sentinel_for<span class="op">&lt;</span>sentinel_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;</span>, </span>
<span id="cb90-2"><a href="#cb90-2" aria-hidden="true" tabindex="-1"></a>                    iterator_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span>
<span id="cb90-3"><a href="#cb90-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">&amp;&amp;</span> <span class="op">(</span>sized_range<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Fs<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></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> <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> iter_move<span class="op">(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> it<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span><em>see below</em><span class="op">)</span>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">39</a></span>
<em>Preconditions</em>: <code class="sourceCode default">it.<em>it_</em>.valueless_by_exception()</code>
is <code class="sourceCode default">false</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">40</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="cf">return</span> std<span class="op">::</span>visit<span class="op">(</span></span>
<span id="cb92-2"><a href="#cb92-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">[](</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> i<span class="op">)</span> <span class="op">-&gt;</span></span>
<span id="cb92-3"><a href="#cb92-3" aria-hidden="true" tabindex="-1"></a>        <em>concat-rvalue-reference-t</em><span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;...&gt;</span> <span class="op">{</span> </span>
<span id="cb92-4"><a href="#cb92-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> ranges<span class="op">::</span>iter_move<span class="op">(</span>i<span class="op">)</span>;</span>
<span id="cb92-5"><a href="#cb92-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>,</span>
<span id="cb92-6"><a href="#cb92-6" aria-hidden="true" tabindex="-1"></a>    it<span class="op">.</span><em>it_</em><span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">41</a></span>
<em>Remarks</em>: The exception specification is equivalent to:</p>
<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="op">((</span>is_nothrow_invocable_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>ranges<span class="op">::</span>iter_move<span class="op">)</span>, </span>
<span id="cb93-2"><a href="#cb93-2" aria-hidden="true" tabindex="-1"></a>                           <span class="kw">const</span> iterator_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;&amp;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb93-3"><a href="#cb93-3" aria-hidden="true" tabindex="-1"></a>  is_nothrow_convertible_v<span class="op">&lt;</span>range_rvalue_reference_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;</span>,</span>
<span id="cb93-4"><a href="#cb93-4" aria-hidden="true" tabindex="-1"></a>                           <em>concat-rvalue-reference-t</em><span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;...&gt;&gt;)</span> <span class="op">&amp;&amp;</span> <span class="op">...)</span></span></code></pre></div>
</div>
<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="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">void</span> iter_swap<span class="op">(</span><span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> x, <span class="kw">const</span> <em>iterator</em><span class="op">&amp;</span> y<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span><em>see below</em><span class="op">)</span></span>
<span id="cb94-2"><a href="#cb94-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <em>see below</em>;</span></code></pre></div>
<div class="bq">
<p><span class="marginalizedparent"><a class="marginalized">42</a></span>
<em>Preconditions</em>: <code class="sourceCode default">x.<em>it_</em>.valueless_by_exception()</code>
and <code class="sourceCode default">y.<em>it_</em>.valueless_by_exception()</code>
are each <code class="sourceCode default">false</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">43</a></span>
<em>Effects</em>: Equivalent to:</p>
<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>std<span class="op">::</span>visit<span class="op">(</span></span>
<span id="cb95-2"><a href="#cb95-2" aria-hidden="true" tabindex="-1"></a>    <span class="op">[&amp;](</span><span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> it1, <span class="kw">const</span> <span class="kw">auto</span><span class="op">&amp;</span> it2<span class="op">)</span> <span class="op">{</span></span>
<span id="cb95-3"><a href="#cb95-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span>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> <span class="op">{</span></span>
<span id="cb95-4"><a href="#cb95-4" aria-hidden="true" tabindex="-1"></a>            ranges<span class="op">::</span>iter_swap<span class="op">(</span>it1, it2<span class="op">)</span>;</span>
<span id="cb95-5"><a href="#cb95-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb95-6"><a href="#cb95-6" aria-hidden="true" tabindex="-1"></a>            ranges<span class="op">::</span>swap<span class="op">(*</span>x, <span class="op">*</span>y<span class="op">)</span>;</span>
<span id="cb95-7"><a href="#cb95-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb95-8"><a href="#cb95-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>,</span>
<span id="cb95-9"><a href="#cb95-9" aria-hidden="true" tabindex="-1"></a>    x<span class="op">.</span><em>it_</em>, y<span class="op">.</span><em>it_</em><span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">44</a></span>
<em>Remarks</em>: The exception specification is 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="op">(</span><span class="kw">noexcept</span><span class="op">(</span>ranges<span class="op">::</span>swap<span class="op">(*</span>x, <span class="op">*</span>y<span class="op">))</span> <span class="op">&amp;&amp;</span> <span class="op">...</span> <span class="op">&amp;&amp;</span> <span class="kw">noexcept</span><span class="op">(</span>ranges<span class="op">::</span>iter_swap<span class="op">(</span>its, its<span class="op">)))</span></span></code></pre></div>
<p>where <code class="sourceCode default">its</code> is a pack of
lvalues of type <code class="sourceCode default">const iterator_t&lt;<em>maybe-const</em>&lt;Const, Views&gt;&gt;</code>
respectively.</p>
<p><span class="marginalizedparent"><a class="marginalized">45</a></span>
<em>Remarks</em>: The expression in the requires-clause is equivalent
to</p>
<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>swappable_with<span class="op">&lt;</span>iter_reference_t<span class="op">&lt;</span><em>iterator</em><span class="op">&gt;</span>, iter_reference_t<span class="op">&lt;</span><em>iterator</em><span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span> </span>
<span id="cb97-2"><a href="#cb97-2" aria-hidden="true" tabindex="-1"></a><span class="op">(...</span> <span class="op">&amp;&amp;</span> indirectly_swappable<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span><em>maybe-const</em><span class="op">&lt;</span>Const, Views<span class="op">&gt;&gt;&gt;)</span></span></code></pre></div>
</div>
<h2 data-number="5.4" id="feature-test-macro"><span class="header-section-number">5.4</span> Feature Test Macro<a href="#feature-test-macro" class="self-link"></a></h2>
<p>Add the following macro definition to <span>17.3.2
<a href="https://wg21.link/version.syn">[version.syn]</a></span>, header
<code class="sourceCode default">&lt;version&gt;</code> synopsis, with
the value selected by the editor to reflect the date of adoption of this
paper:</p>
<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="pp">#define __cpp_lib_ranges_concat  </span><span class="dv">20</span><span class="er">XXXXL</span><span class="pp"> </span><span class="co">// also in &lt;ranges&gt;</span></span></code></pre></div>
<style>
.bq{
    display: block;
    margin-block-start: 1em;
    margin-block-end: 1em;
    margin-inline-start: 40px;
    margin-inline-end: 40px;
}
</style>
<h1 data-number="6" id="bibliography"><span class="header-section-number">6</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">
<div id="ref-ours" class="csl-entry" role="doc-biblioentry">
[ours] Hui Xie and S. Levent Yilmaz. A proof-of-concept implementation
of views::concat. <a href="https://github.com/huixie90/cpp_papers/tree/main/impl/concat"><div class="csl-block">https://github.com/huixie90/cpp_papers/tree/main/impl/concat</div></a>
</div>
<div id="ref-P2214R1" class="csl-entry" role="doc-biblioentry">
[P2214R1] Barry Revzin, Conor Hoekstra, Tim Song. 2021-09-14. A Plan for
C++23 Ranges. <a href="https://wg21.link/p2214r1"><div class="csl-block">https://wg21.link/p2214r1</div></a>
</div>
<div id="ref-P2278R1" class="csl-entry" role="doc-biblioentry">
[P2278R1] Barry Revzin. 2021-09-15. cbegin should always return a
constant iterator. <a href="https://wg21.link/p2278r1"><div class="csl-block">https://wg21.link/p2278r1</div></a>
</div>
<div id="ref-P2321R2" class="csl-entry" role="doc-biblioentry">
[P2321R2] Tim Song. 2021-06-11. zip. <a href="https://wg21.link/p2321r2"><div class="csl-block">https://wg21.link/p2321r2</div></a>
</div>
<div id="ref-P2374R3" class="csl-entry" role="doc-biblioentry">
[P2374R3] Sy Brand, Michał Dominiak. 2021-12-13.
views::cartesian_product. <a href="https://wg21.link/p2374r3"><div class="csl-block">https://wg21.link/p2374r3</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>
