<!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="2022-11-20" />
  <title>`std::iterator_interface`</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">std::iterator_interface</code></h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2727R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2022-11-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>
      LEWG-I<br>
      LEWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Zach Laine<br>&lt;<a href="mailto:whatwasthataddress@gmail.com" class="email">whatwasthataddress@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="#changelog" id="toc-changelog"><span class="toc-section-number">1</span> Changelog<span></span></a>
<ul>
<li><a href="#changes-since-r0" id="toc-changes-since-r0"><span class="toc-section-number">1.1</span> Changes since
R0<span></span></a></li>
</ul></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">2</span> Motivation<span></span></a>
<ul>
<li><a href="#the-story-for-everyday-users-writing-stl-iterators-is-not-great" id="toc-the-story-for-everyday-users-writing-stl-iterators-is-not-great"><span class="toc-section-number">2.1</span> The story for everyday users
writing STL iterators is not great<span></span></a></li>
<li><a href="#writing-stl-iterators-is-very-useful" id="toc-writing-stl-iterators-is-very-useful"><span class="toc-section-number">2.2</span> Writing STL iterators is very
useful<span></span></a></li>
<li><a href="#iterator-adaptation" id="toc-iterator-adaptation"><span class="toc-section-number">2.3</span> Iterator
adaptation<span></span></a></li>
</ul></li>
<li><a href="#proposed-design" id="toc-proposed-design"><span class="toc-section-number">3</span> Proposed design<span></span></a>
<ul>
<li><a href="#add-iterator_interface_access" id="toc-add-iterator_interface_access"><span class="toc-section-number">3.1</span> Add
<code class="sourceCode default">iterator_interface_access</code><span></span></a></li>
<li><a href="#add-proxy_arrow_result" id="toc-add-proxy_arrow_result"><span class="toc-section-number">3.2</span> Add
<code class="sourceCode default">proxy_arrow_result</code><span></span></a></li>
<li><a href="#add-iterator_interface-itself" id="toc-add-iterator_interface-itself"><span class="toc-section-number">3.3</span> Add
<code class="sourceCode default">iterator_interface</code>
itself<span></span></a></li>
<li><a href="#add-operator-overload" id="toc-add-operator-overload"><span class="toc-section-number">3.4</span> Add
<code class="sourceCode default">operator==</code>
overload<span></span></a></li>
<li><a href="#add-proxy_iterator_interface" id="toc-add-proxy_iterator_interface"><span class="toc-section-number">3.5</span> Add
<code class="sourceCode default">proxy_iterator_interface</code><span></span></a></li>
<li><a href="#add-a-feature-test-macro" id="toc-add-a-feature-test-macro"><span class="toc-section-number">3.6</span> Add a feature test
macro<span></span></a></li>
<li><a href="#design-notes" id="toc-design-notes"><span class="toc-section-number">3.7</span> Design notes<span></span></a>
<ul>
<li><a href="#nested-typedefs-in-the-dependent-base-case" id="toc-nested-typedefs-in-the-dependent-base-case"><span class="toc-section-number">3.7.1</span> Nested typedefs in the
dependent-base case<span></span></a></li>
<li><a href="#the-name-iterator_interface" id="toc-the-name-iterator_interface"><span class="toc-section-number">3.7.2</span> The name
<code class="sourceCode default">iterator_interface</code><span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#performance" id="toc-performance"><span class="toc-section-number">4</span> Performance<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">5</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="changelog"><span class="header-section-number">1</span> Changelog<a href="#changelog" class="self-link"></a></h1>
<h2 data-number="1.1" id="changes-since-r0"><span class="header-section-number">1.1</span> Changes since R0<a href="#changes-since-r0" class="self-link"></a></h2>
<ul>
<li>Added discussion about nested typedefs in dependent-base cases.</li>
<li>Added an alternate name.</li>
<li>Added discussion about performance.</li>
<li>Typos.</li>
</ul>
<h1 data-number="2" id="motivation"><span class="header-section-number">2</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<h2 data-number="2.1" id="the-story-for-everyday-users-writing-stl-iterators-is-not-great"><span class="header-section-number">2.1</span> The story for everyday users
writing STL iterators is not great<a href="#the-story-for-everyday-users-writing-stl-iterators-is-not-great" class="self-link"></a></h2>
<p>Writing STL iterators is surprisingly hard. There are a lot of things
that can subtly go wrong. It is also very tedious, which of course makes
it error-prone.</p>
<p>Iterators have numerous typedefs and operations, even though all the
operations of a given iterator can be implemented in terms of at most
four operations (and usually only three). Writing all the other
operations yields very similar-looking code that is hard to review, and
all but requires that you write full-coverage tests for each
iterator.</p>
<p>As an example, say you wanted an iterator that allowed you to iterate
over repetitions of a sequence of characters, like:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>repeated_chars_iterator first<span class="op">(</span><span class="st">&quot;foo&quot;</span>, <span class="dv">3</span>, <span class="dv">0</span><span class="op">)</span>; <span class="co">// 3 is the length of &quot;foo&quot;, 0 is this iterator&#39;s position.</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>repeated_chars_iterator last<span class="op">(</span><span class="st">&quot;foo&quot;</span>, <span class="dv">3</span>, <span class="dv">7</span><span class="op">)</span>;  <span class="co">// Same as above, but now the iterator&#39;s position is 7.</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>string result;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>copy<span class="op">(</span>first, last, std<span class="op">::</span>back_inserter<span class="op">(</span>result<span class="op">))</span>;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>result <span class="op">==</span> <span class="st">&quot;foofoof&quot;</span><span class="op">)</span>;</span></code></pre></div>
<p>Here’s how you might implement it, with and without this
proposal:</p>
<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="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> repeated_chars_iterator</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> value_type <span class="op">=</span> <span class="dt">char</span>;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> difference_type <span class="op">=</span> std<span class="op">::</span><span class="dt">ptrdiff_t</span>;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> pointer <span class="op">=</span> <span class="dt">char</span> <span class="kw">const</span> <span class="op">*</span>;</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> reference <span class="op">=</span> <span class="dt">char</span> <span class="kw">const</span>;</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator_category <span class="op">=</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>random_access_iterator_tag;</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> repeated_chars_iterator<span class="op">()</span> <span class="op">:</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>        first_<span class="op">(</span><span class="kw">nullptr</span><span class="op">)</span>,</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>        size_<span class="op">(</span><span class="dv">0</span><span class="op">)</span>,</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a>        n_<span class="op">(</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">{}</span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> repeated_chars_iterator<span class="op">(</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a>        <span class="dt">char</span> <span class="kw">const</span> <span class="op">*</span> first,</span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a>        difference_type size,</span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a>        difference_type n<span class="op">)</span> <span class="op">:</span></span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a>        first_<span class="op">(</span>first<span class="op">)</span>,</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a>        size_<span class="op">(</span>size<span class="op">)</span>,</span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a>        n_<span class="op">(</span>n<span class="op">)</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">{}</span></span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> reference <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> first_<span class="op">[</span>n_ <span class="op">%</span> size_<span class="op">]</span>;</span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-28"><a href="#cb2-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-29"><a href="#cb2-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> value_type <span class="kw">operator</span><span class="op">[](</span></span>
<span id="cb2-30"><a href="#cb2-30" aria-hidden="true" tabindex="-1"></a>        difference_type n<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb2-31"><a href="#cb2-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-32"><a href="#cb2-32" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> first_<span class="op">[(</span>n_ <span class="op">+</span> n<span class="op">)</span> <span class="op">%</span> size_<span class="op">]</span>;</span>
<span id="cb2-33"><a href="#cb2-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-34"><a href="#cb2-34" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-35"><a href="#cb2-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> repeated_chars_iterator <span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span></span>
<span id="cb2-36"><a href="#cb2-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-37"><a href="#cb2-37" aria-hidden="true" tabindex="-1"></a>        <span class="op">++</span>n_;</span>
<span id="cb2-38"><a href="#cb2-38" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb2-39"><a href="#cb2-39" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-40"><a href="#cb2-40" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> repeated_chars_iterator</span>
<span id="cb2-41"><a href="#cb2-41" aria-hidden="true" tabindex="-1"></a>    <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span><span class="kw">noexcept</span></span>
<span id="cb2-42"><a href="#cb2-42" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-43"><a href="#cb2-43" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator retval <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb2-44"><a href="#cb2-44" aria-hidden="true" tabindex="-1"></a>        <span class="op">++*</span><span class="kw">this</span>;</span>
<span id="cb2-45"><a href="#cb2-45" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> retval;</span>
<span id="cb2-46"><a href="#cb2-46" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-47"><a href="#cb2-47" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> repeated_chars_iterator <span class="op">&amp;</span></span>
<span id="cb2-48"><a href="#cb2-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">operator</span><span class="op">+=(</span>difference_type n<span class="op">)</span></span>
<span id="cb2-49"><a href="#cb2-49" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-50"><a href="#cb2-50" aria-hidden="true" tabindex="-1"></a>        n_ <span class="op">+=</span> n;</span>
<span id="cb2-51"><a href="#cb2-51" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb2-52"><a href="#cb2-52" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-53"><a href="#cb2-53" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-54"><a href="#cb2-54" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> repeated_chars_iterator <span class="op">&amp;</span> <span class="kw">operator</span><span class="op">--()</span></span>
<span id="cb2-55"><a href="#cb2-55" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-56"><a href="#cb2-56" aria-hidden="true" tabindex="-1"></a>        <span class="op">--</span>n_;</span>
<span id="cb2-57"><a href="#cb2-57" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb2-58"><a href="#cb2-58" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-59"><a href="#cb2-59" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> repeated_chars_iterator</span>
<span id="cb2-60"><a href="#cb2-60" aria-hidden="true" tabindex="-1"></a>    <span class="kw">operator</span><span class="op">--(</span><span class="dt">int</span><span class="op">)</span><span class="kw">noexcept</span></span>
<span id="cb2-61"><a href="#cb2-61" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-62"><a href="#cb2-62" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator retval <span class="op">=</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb2-63"><a href="#cb2-63" aria-hidden="true" tabindex="-1"></a>        <span class="op">--*</span><span class="kw">this</span>;</span>
<span id="cb2-64"><a href="#cb2-64" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> retval;</span>
<span id="cb2-65"><a href="#cb2-65" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-66"><a href="#cb2-66" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> repeated_chars_iterator <span class="op">&amp;</span></span>
<span id="cb2-67"><a href="#cb2-67" aria-hidden="true" tabindex="-1"></a>    <span class="kw">operator</span><span class="op">-=(</span>difference_type n<span class="op">)</span></span>
<span id="cb2-68"><a href="#cb2-68" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-69"><a href="#cb2-69" aria-hidden="true" tabindex="-1"></a>        n_ <span class="op">-=</span> n;</span>
<span id="cb2-70"><a href="#cb2-70" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb2-71"><a href="#cb2-71" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-72"><a href="#cb2-72" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-73"><a href="#cb2-73" 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>
<span id="cb2-74"><a href="#cb2-74" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator lhs,</span>
<span id="cb2-75"><a href="#cb2-75" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator rhs<span class="op">)</span></span>
<span id="cb2-76"><a href="#cb2-76" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-77"><a href="#cb2-77" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> lhs<span class="op">.</span>first_ <span class="op">==</span> rhs<span class="op">.</span>first_ <span class="op">&amp;&amp;</span></span>
<span id="cb2-78"><a href="#cb2-78" aria-hidden="true" tabindex="-1"></a>            lhs<span class="op">.</span>n_ <span class="op">==</span> rhs<span class="op">.</span>n_;</span>
<span id="cb2-79"><a href="#cb2-79" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-80"><a href="#cb2-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">!=(</span></span>
<span id="cb2-81"><a href="#cb2-81" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator lhs,</span>
<span id="cb2-82"><a href="#cb2-82" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator rhs<span class="op">)</span></span>
<span id="cb2-83"><a href="#cb2-83" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-84"><a href="#cb2-84" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">!(</span>lhs <span class="op">==</span> rhs<span class="op">)</span>;</span>
<span id="cb2-85"><a href="#cb2-85" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-86"><a href="#cb2-86" 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>
<span id="cb2-87"><a href="#cb2-87" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator lhs,</span>
<span id="cb2-88"><a href="#cb2-88" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator rhs<span class="op">)</span></span>
<span id="cb2-89"><a href="#cb2-89" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-90"><a href="#cb2-90" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> lhs<span class="op">.</span>first_ <span class="op">==</span> rhs<span class="op">.</span>first_ <span class="op">&amp;&amp;</span></span>
<span id="cb2-91"><a href="#cb2-91" aria-hidden="true" tabindex="-1"></a>            lhs<span class="op">.</span>n_ <span class="op">&lt;</span> rhs<span class="op">.</span>n_;</span>
<span id="cb2-92"><a href="#cb2-92" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-93"><a href="#cb2-93" 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>
<span id="cb2-94"><a href="#cb2-94" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator lhs,</span>
<span id="cb2-95"><a href="#cb2-95" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator rhs<span class="op">)</span></span>
<span id="cb2-96"><a href="#cb2-96" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-97"><a href="#cb2-97" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> lhs <span class="op">==</span> rhs <span class="op">||</span> lhs <span class="op">&lt;</span> rhs;</span>
<span id="cb2-98"><a href="#cb2-98" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-99"><a href="#cb2-99" 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>
<span id="cb2-100"><a href="#cb2-100" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator lhs,</span>
<span id="cb2-101"><a href="#cb2-101" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator rhs<span class="op">)</span></span>
<span id="cb2-102"><a href="#cb2-102" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-103"><a href="#cb2-103" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> rhs <span class="op">&lt;</span> lhs;</span>
<span id="cb2-104"><a href="#cb2-104" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-105"><a href="#cb2-105" 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>
<span id="cb2-106"><a href="#cb2-106" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator lhs,</span>
<span id="cb2-107"><a href="#cb2-107" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator rhs<span class="op">)</span></span>
<span id="cb2-108"><a href="#cb2-108" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-109"><a href="#cb2-109" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> lhs <span class="op">&lt;=</span> rhs;</span>
<span id="cb2-110"><a href="#cb2-110" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-111"><a href="#cb2-111" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-112"><a href="#cb2-112" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> repeated_chars_iterator</span>
<span id="cb2-113"><a href="#cb2-113" aria-hidden="true" tabindex="-1"></a>    <span class="kw">operator</span><span class="op">+(</span>repeated_chars_iterator lhs,</span>
<span id="cb2-114"><a href="#cb2-114" aria-hidden="true" tabindex="-1"></a>              difference_type rhs<span class="op">)</span></span>
<span id="cb2-115"><a href="#cb2-115" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-116"><a href="#cb2-116" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> lhs <span class="op">+=</span> rhs;</span>
<span id="cb2-117"><a href="#cb2-117" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-118"><a href="#cb2-118" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> repeated_chars_iterator</span>
<span id="cb2-119"><a href="#cb2-119" aria-hidden="true" tabindex="-1"></a>    <span class="kw">operator</span><span class="op">+(</span>difference_type lhs,</span>
<span id="cb2-120"><a href="#cb2-120" aria-hidden="true" tabindex="-1"></a>              repeated_chars_iterator rhs<span class="op">)</span></span>
<span id="cb2-121"><a href="#cb2-121" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-122"><a href="#cb2-122" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> rhs <span class="op">+=</span> lhs;</span>
<span id="cb2-123"><a href="#cb2-123" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-124"><a href="#cb2-124" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="kw">constexpr</span> repeated_chars_iterator</span>
<span id="cb2-125"><a href="#cb2-125" aria-hidden="true" tabindex="-1"></a>    <span class="kw">operator</span><span class="op">-(</span>repeated_chars_iterator lhs,</span>
<span id="cb2-126"><a href="#cb2-126" aria-hidden="true" tabindex="-1"></a>              difference_type rhs<span class="op">)</span></span>
<span id="cb2-127"><a href="#cb2-127" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-128"><a href="#cb2-128" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> lhs <span class="op">-=</span> rhs;</span>
<span id="cb2-129"><a href="#cb2-129" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-130"><a href="#cb2-130" 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>
<span id="cb2-131"><a href="#cb2-131" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator lhs,</span>
<span id="cb2-132"><a href="#cb2-132" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator rhs<span class="op">)</span></span>
<span id="cb2-133"><a href="#cb2-133" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb2-134"><a href="#cb2-134" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> lhs<span class="op">.</span>n_ <span class="op">-</span> rhs<span class="op">.</span>n_;</span>
<span id="cb2-135"><a href="#cb2-135" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-136"><a href="#cb2-136" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-137"><a href="#cb2-137" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb2-138"><a href="#cb2-138" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> <span class="kw">const</span> <span class="op">*</span> first_;</span>
<span id="cb2-139"><a href="#cb2-139" aria-hidden="true" tabindex="-1"></a>    difference_type size_;</span>
<span id="cb2-140"><a href="#cb2-140" aria-hidden="true" tabindex="-1"></a>    difference_type n_;</span>
<span id="cb2-141"><a href="#cb2-141" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
<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">struct</span> repeated_chars_iterator <span class="op">:</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>iterator_interface<span class="op">&lt;</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator,</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        std<span class="op">::</span>random_access_iterator_tag,</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        <span class="dt">char</span>,</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>        <span class="dt">char</span><span class="op">&gt;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> repeated_chars_iterator<span class="op">()</span> <span class="op">:</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>        first_<span class="op">(</span><span class="kw">nullptr</span><span class="op">)</span>,</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>        size_<span class="op">(</span><span class="dv">0</span><span class="op">)</span>,</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>        n_<span class="op">(</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">{}</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> repeated_chars_iterator<span class="op">(</span><span class="dt">char</span> <span class="kw">const</span> <span class="op">*</span> first,</span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>                                      difference_type size,</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>                                      difference_type n<span class="op">)</span> <span class="op">:</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>        first_<span class="op">(</span>first<span class="op">)</span>,</span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a>        size_<span class="op">(</span>size<span class="op">)</span>,</span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true" tabindex="-1"></a>        n_<span class="op">(</span>n<span class="op">)</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">{}</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="dt">char</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</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 class="cf">return</span> first_<span class="op">[</span>n_ <span class="op">%</span> size_<span class="op">]</span>;</span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> repeated_chars_iterator <span class="op">&amp;</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">operator</span><span class="op">+=(</span>std<span class="op">::</span><span class="dt">ptrdiff_t</span> i<span class="op">)</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true" tabindex="-1"></a>        n_ <span class="op">+=</span> i;</span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-(</span></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true" tabindex="-1"></a>        repeated_chars_iterator other<span class="op">)</span> <span class="kw">const</span></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> n_ <span class="op">-</span> other<span class="op">.</span>n_;</span>
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb3-38"><a href="#cb3-38" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> <span class="kw">const</span> <span class="op">*</span> first_;</span>
<span id="cb3-39"><a href="#cb3-39" aria-hidden="true" tabindex="-1"></a>    difference_type size_;</span>
<span id="cb3-40"><a href="#cb3-40" aria-hidden="true" tabindex="-1"></a>    difference_type n_;</span>
<span id="cb3-41"><a href="#cb3-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>I used that motivating example in the README file for the Boost
library this proposal is based on. One day, someone pointed out that
there was a bug in the “before” version of the iterator. The iterator
was used extensively in yet another proposed Boost library of mine, and
yet this bug was never actually exercised that I know of. This
underscores an important point: with very large APIs like the std
iterators, one is very likely to use lots of copy pasta, and one is very
unlikely to fully test each element of the API.</p>
<p>I’ve reintroduced the bug here for funsies; see how long it takes you
to find it by inspection.</p>
<h2 data-number="2.2" id="writing-stl-iterators-is-very-useful"><span class="header-section-number">2.2</span> Writing STL iterators is very
useful<a href="#writing-stl-iterators-is-very-useful" class="self-link"></a></h2>
<p>Some examples of useful iterators you may want to write:</p>
<ul>
<li>Checking iterators that do certain checks only in debug builds.</li>
<li>Iterators that adapt legacy container-like types for use with STL
algorithms and containers.</li>
<li><em>Ad hoc</em>, single-application iterators.</li>
</ul>
<p>Because writing iterators is so much work at the moment, most of us
avoid it whenever possible. So <em>ad hoc</em> use cases for iterators
almost always go unfulfilled. Here’s an example of one such <em>ad
hoc</em> iterator use case.</p>
<p>Say you have two or more sequences that you want to treat as a single
sequence:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> a;</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>list<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> b;</span></code></pre></div>
<p>You’d use something like the
<code class="sourceCode default">views::concat</code> proposed in <span class="citation" data-cites="P2542R2">[<a href="#ref-P2542R2" role="doc-biblioref">P2542R2</a>]</span>:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> <span class="op">&amp;&amp;</span> x <span class="op">:</span> concat<span class="op">(</span>a, b<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="co">// ...</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>That works well, as long as there exists a common reference type
among the iterators used within the
<code class="sourceCode default">views::concat</code> implementation.
What if there isn’t? What if the
<code class="sourceCode default">value_type</code>s of the various
ranges you pass to <code class="sourceCode default">concat()</code> are
essentially compatible, but nevertheless have no common reference
type?</p>
<p>For example, what if I want to concatenate two ranges, one of which
is a range of <code class="sourceCode default">int</code> and the other
of which is a range of:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> my_int</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    my_int<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> my_int<span class="op">(</span><span class="dt">int</span> v<span class="op">)</span> <span class="op">:</span> value_<span class="op">{</span>v<span class="op">}</span> <span class="op">{}</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> value_;</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Clearly, <code class="sourceCode default">std::common_reference_with&lt;my_int, int&gt;</code>
is <code class="sourceCode default">false</code>. However, if I also had
some simple way of projecting from either one to
<code class="sourceCode default">int</code>, like this:</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="dt">int</span> as_int<span class="op">(</span><span class="dt">int</span> i<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> i; <span class="op">}</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> as_int<span class="op">(</span>my_int i<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> i<span class="op">.</span>value_; <span class="op">}</span></span></code></pre></div>
<p>I would still expect to be able to construct some view over the
concatenation of <code class="sourceCode default">a</code> and
<code class="sourceCode default">b</code> – even if it were
read-only.</p>
<p>This example may seem contrived, but it is not. While implementing an
algorithm to support Unicode operations on strings, I ran in to a case
in which a certain step <code class="sourceCode default">S</code> of the
algorithm required iterating over two containers
<code class="sourceCode default">A a</code> and
<code class="sourceCode default">B b</code>, where
<code class="sourceCode default">A::iterator::reference</code> and
<code class="sourceCode default">B::iterator::reference</code> were
different enough that there was no common reference, but
<code class="sourceCode default">A::value_type</code> and
<code class="sourceCode default">B::value_type</code> were similar
enough that I could just call a function (analogous to
<code class="sourceCode default">as_int()</code> above) that could
project both of them to a single type. To make matters worse, I could
not even break <code class="sourceCode default">S</code> up into the
<code class="sourceCode default">a</code>-part and the
<code class="sourceCode default">b</code>-part, because
<code class="sourceCode default">S</code> could not consider elements in
isolation; it required examining adjacent elements in the concatenation
of <code class="sourceCode default">a</code> and
<code class="sourceCode default">b</code>.</p>
<p>None of the views proposed for the standard has ever supported
projections. I don’t consider this a defect; it’s probably the wrong
kind of customization for a general-purpose view. So, what to do? Write
an iterator that fits this one-off, special case, of course! Using <a href="https://github.com/boostorg/stl_interfaces">Boost.STLInterfaces</a>,
an implementation of everything in this proposal and more, I wrote
something like this iterator. To keep all the Unicode-y bits out of our
way, I’m showing the
<code class="sourceCode default">int</code>/<code class="sourceCode default">my_int</code>
analogous solution.</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="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> Proj, <span class="kw">typename</span> R1, <span class="kw">typename</span> R2<span class="op">&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> concat_iter <span class="op">:</span> boost<span class="op">::</span>stl_interfaces<span class="op">::</span>proxy_iterator_interface<span class="op">&lt;</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>                         concat_iter<span class="op">&lt;</span>T, Proj, R1, R2<span class="op">&gt;</span>,</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>                         std<span class="op">::</span>bidirectional_iterator_tag,</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>                         T<span class="op">&gt;</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> first_iterator <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span>std<span class="op">::</span>declval<span class="op">&lt;</span>R1 <span class="op">&amp;&gt;().</span>begin<span class="op">())</span>;</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> second_iterator <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span>std<span class="op">::</span>declval<span class="op">&lt;</span>R2 <span class="op">&amp;&gt;().</span>begin<span class="op">())</span>;</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> end_tag<span class="op">{}</span>;</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>    concat_iter<span class="op">()</span> <span class="op">:</span> in_r1_<span class="op">(</span><span class="kw">false</span><span class="op">)</span> <span class="op">{}</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>    concat_iter<span class="op">(</span>first_iterator it,</span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>                first_iterator r1_last,</span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>                second_iterator r2_first,</span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a>                Proj proj<span class="op">)</span> <span class="op">:</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>        r1_last_<span class="op">(</span>r1_last<span class="op">)</span>,</span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a>        it1_<span class="op">(</span>it<span class="op">)</span>,</span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true" tabindex="-1"></a>        r2_first_<span class="op">(</span>r2_first<span class="op">)</span>,</span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true" tabindex="-1"></a>        it2_<span class="op">(</span>r2_first<span class="op">)</span>,</span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true" tabindex="-1"></a>        proj_<span class="op">(</span>proj<span class="op">)</span>,</span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true" tabindex="-1"></a>        in_r1_<span class="op">(</span><span class="kw">true</span><span class="op">)</span></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>it1_ <span class="op">==</span> r1_last_<span class="op">)</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true" tabindex="-1"></a>            in_r1_ <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true" tabindex="-1"></a>    concat_iter<span class="op">(</span>second_iterator it,</span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true" tabindex="-1"></a>                first_iterator r1_last,</span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true" tabindex="-1"></a>                second_iterator r2_first,</span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true" tabindex="-1"></a>                Proj proj,</span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true" tabindex="-1"></a>                end_tag<span class="op">)</span> <span class="op">:</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true" tabindex="-1"></a>        r1_last_<span class="op">(</span>r1_last<span class="op">)</span>,</span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true" tabindex="-1"></a>        it1_<span class="op">(</span>r1_last<span class="op">)</span>,</span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true" tabindex="-1"></a>        r2_first_<span class="op">(</span>r2_first<span class="op">)</span>,</span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true" tabindex="-1"></a>        it2_<span class="op">(</span>it<span class="op">)</span>,</span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true" tabindex="-1"></a>        proj_<span class="op">(</span>proj<span class="op">)</span>,</span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true" tabindex="-1"></a>        in_r1_<span class="op">(</span><span class="kw">false</span><span class="op">)</span></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true" tabindex="-1"></a>    <span class="op">{}</span></span>
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true" tabindex="-1"></a>    concat_iter <span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span> <span class="kw">noexcept</span></span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(</span>in_r1_<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true" tabindex="-1"></a>            <span class="ot">assert</span><span class="op">(</span>it1_ <span class="op">!=</span> r1_last_<span class="op">)</span>;</span>
<span id="cb8-43"><a href="#cb8-43" aria-hidden="true" tabindex="-1"></a>            <span class="op">++</span>it1_;</span>
<span id="cb8-44"><a href="#cb8-44" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>it1_ <span class="op">==</span> r1_last_<span class="op">)</span></span>
<span id="cb8-45"><a href="#cb8-45" aria-hidden="true" tabindex="-1"></a>                in_r1_ <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb8-46"><a href="#cb8-46" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb8-47"><a href="#cb8-47" aria-hidden="true" tabindex="-1"></a>            <span class="op">++</span>it2_;</span>
<span id="cb8-48"><a href="#cb8-48" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb8-49"><a href="#cb8-49" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb8-50"><a href="#cb8-50" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-51"><a href="#cb8-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-52"><a href="#cb8-52" aria-hidden="true" tabindex="-1"></a>    concat_iter <span class="op">&amp;</span> <span class="kw">operator</span><span class="op">--()</span> <span class="kw">noexcept</span></span>
<span id="cb8-53"><a href="#cb8-53" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb8-54"><a href="#cb8-54" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> <span class="op">(!</span>in_r1_<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-55"><a href="#cb8-55" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(</span>it2_ <span class="op">==</span> r2_first_<span class="op">)</span> <span class="op">{</span></span>
<span id="cb8-56"><a href="#cb8-56" aria-hidden="true" tabindex="-1"></a>                in_r1_ <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb8-57"><a href="#cb8-57" aria-hidden="true" tabindex="-1"></a>                <span class="op">--</span>it1_;</span>
<span id="cb8-58"><a href="#cb8-58" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb8-59"><a href="#cb8-59" aria-hidden="true" tabindex="-1"></a>                <span class="op">--</span>it2_;</span>
<span id="cb8-60"><a href="#cb8-60" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb8-61"><a href="#cb8-61" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb8-62"><a href="#cb8-62" aria-hidden="true" tabindex="-1"></a>            <span class="op">--</span>it1_;</span>
<span id="cb8-63"><a href="#cb8-63" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb8-64"><a href="#cb8-64" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb8-65"><a href="#cb8-65" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-66"><a href="#cb8-66" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-67"><a href="#cb8-67" aria-hidden="true" tabindex="-1"></a>    T <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span> <span class="kw">noexcept</span></span>
<span id="cb8-68"><a href="#cb8-68" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb8-69"><a href="#cb8-69" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> in_r1_ <span class="op">?</span> proj_<span class="op">(*</span>it1_<span class="op">)</span> <span class="op">:</span> proj_<span class="op">(*</span>it2_<span class="op">)</span>;</span>
<span id="cb8-70"><a href="#cb8-70" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-71"><a href="#cb8-71" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-72"><a href="#cb8-72" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>concat_iter lhs, concat_iter rhs<span class="op">)</span></span>
<span id="cb8-73"><a href="#cb8-73" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb8-74"><a href="#cb8-74" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> lhs<span class="op">.</span>in_r1_ <span class="op">==</span> rhs<span class="op">.</span>in_r1_ <span class="op">&amp;&amp;</span></span>
<span id="cb8-75"><a href="#cb8-75" aria-hidden="true" tabindex="-1"></a>               <span class="op">(</span>lhs<span class="op">.</span>in_r1_ <span class="op">?</span></span>
<span id="cb8-76"><a href="#cb8-76" aria-hidden="true" tabindex="-1"></a>                lhs<span class="op">.</span>it1_ <span class="op">==</span> rhs<span class="op">.</span>it1_ <span class="op">:</span> lhs<span class="op">.</span>it2_ <span class="op">==</span> rhs<span class="op">.</span>it2_<span class="op">)</span>;</span>
<span id="cb8-77"><a href="#cb8-77" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb8-78"><a href="#cb8-78" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-79"><a href="#cb8-79" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> base_type <span class="op">=</span></span>
<span id="cb8-80"><a href="#cb8-80" aria-hidden="true" tabindex="-1"></a>        boost<span class="op">::</span>stl_interfaces<span class="op">::</span>proxy_iterator_interface<span class="op">&lt;</span></span>
<span id="cb8-81"><a href="#cb8-81" aria-hidden="true" tabindex="-1"></a>            concat_iter<span class="op">&lt;</span>T, Proj, R1, R2<span class="op">&gt;</span>,</span>
<span id="cb8-82"><a href="#cb8-82" aria-hidden="true" tabindex="-1"></a>            std<span class="op">::</span>bidirectional_iterator_tag,</span>
<span id="cb8-83"><a href="#cb8-83" aria-hidden="true" tabindex="-1"></a>            T<span class="op">&gt;</span>;</span>
<span id="cb8-84"><a href="#cb8-84" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> base_type<span class="op">::</span><span class="kw">operator</span><span class="op">++</span>;</span>
<span id="cb8-85"><a href="#cb8-85" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> base_type<span class="op">::</span><span class="kw">operator</span><span class="op">--</span>;</span>
<span id="cb8-86"><a href="#cb8-86" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-87"><a href="#cb8-87" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb8-88"><a href="#cb8-88" aria-hidden="true" tabindex="-1"></a>    first_iterator r1_last_;</span>
<span id="cb8-89"><a href="#cb8-89" aria-hidden="true" tabindex="-1"></a>    first_iterator it1_;</span>
<span id="cb8-90"><a href="#cb8-90" aria-hidden="true" tabindex="-1"></a>    second_iterator r2_first_;</span>
<span id="cb8-91"><a href="#cb8-91" aria-hidden="true" tabindex="-1"></a>    second_iterator it2_;</span>
<span id="cb8-92"><a href="#cb8-92" aria-hidden="true" tabindex="-1"></a>    Proj proj_;</span>
<span id="cb8-93"><a href="#cb8-93" aria-hidden="true" tabindex="-1"></a>    <span class="dt">bool</span> in_r1_;</span>
<span id="cb8-94"><a href="#cb8-94" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>That’s a pleasantly low amount of code to write, and I was able to
avoid implementing most of the boilerplate bits – the operations that
need to exist for my type to be conforming bidirectional iterator, but I
which I will not explicitly use.</p>
<p>In case you were wondering about the
<code class="sourceCode default">T</code> template parameter, that just
gets around the need for some potentially-messy metaprogramming to
determine what <code class="sourceCode default">concat_iter</code>’s
<code class="sourceCode default">value_type</code> is – it’s whatever
you specify for <code class="sourceCode default">T</code>.</p>
<p>With the iterator in hand, it becomes trivial to construct a
<code class="sourceCode default">concat_view</code>, and a
<code class="sourceCode default">concat()</code> function:</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">typename</span> T, <span class="kw">typename</span> R1, <span class="kw">typename</span> R2<span class="op">&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> concat_view</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> std<span class="op">::</span>view_interface<span class="op">&lt;</span>concat_view<span class="op">&lt;</span>T, R1, R2<span class="op">&gt;&gt;</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator <span class="op">=</span> concat_iter<span class="op">&lt;</span>T, R1, R2<span class="op">&gt;</span>;</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    concat_view<span class="op">(</span>iterator first, iterator last<span class="op">)</span> <span class="op">:</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>        first_<span class="op">(</span>first<span class="op">)</span>, last_<span class="op">(</span>last<span class="op">)</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    <span class="op">{}</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>    iterator begin<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> first_; <span class="op">}</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a>    iterator end<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> last_; <span class="op">}</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a>    iterator first_;</span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a>    iterator last_;</span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T, <span class="kw">typename</span> R1, <span class="kw">typename</span> R2, <span class="kw">typename</span> Proj<span class="op">&gt;</span></span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> concat<span class="op">(</span>R1 <span class="op">&amp;</span> r1, R2 <span class="op">&amp;</span> r2, Proj proj<span class="op">)</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">using</span> iterator <span class="op">=</span> concat_iter<span class="op">&lt;</span>T, Proj, R1, R2<span class="op">&gt;</span>;</span>
<span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> concat_view<span class="op">&lt;</span>T, R1, R2<span class="op">&gt;(</span></span>
<span id="cb9-24"><a href="#cb9-24" aria-hidden="true" tabindex="-1"></a>        iterator<span class="op">(</span>r1<span class="op">.</span>begin<span class="op">()</span>, r1<span class="op">.</span>end<span class="op">()</span>, r2<span class="op">.</span>begin<span class="op">()</span>, proj<span class="op">)</span>,</span>
<span id="cb9-25"><a href="#cb9-25" aria-hidden="true" tabindex="-1"></a>        iterator<span class="op">(</span>r2<span class="op">.</span>end<span class="op">()</span>, r1<span class="op">.</span>end<span class="op">()</span>, r2<span class="op">.</span>begin<span class="op">()</span>, proj,</span>
<span id="cb9-26"><a href="#cb9-26" aria-hidden="true" tabindex="-1"></a>                 iterator<span class="op">::</span>end_tag<span class="op">{}))</span>;</span>
<span id="cb9-27"><a href="#cb9-27" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Finally, here it is at the point of use:</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>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> vec <span class="op">=</span> <span class="op">{</span> <span class="dv">0</span>, <span class="dv">58</span>, <span class="dv">48</span> <span class="op">}</span>;</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>list<span class="op">&lt;</span>my_int<span class="op">&gt;</span> list <span class="op">=</span> <span class="op">{</span> <span class="dv">80</span>, <span class="dv">39</span> <span class="op">}</span>;</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> <span class="kw">const</span> v <span class="op">=</span> concat<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;(</span>vec, list, <span class="op">[](</span><span class="kw">auto</span> x<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> as_int<span class="op">(</span>x<span class="op">)</span>; <span class="op">})</span>;</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>std<span class="op">::</span>ranges<span class="op">::</span>find<span class="op">(</span>v, <span class="dv">42</span><span class="op">)</span> <span class="op">==</span> v<span class="op">.</span>end<span class="op">())</span>;</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>std<span class="op">::</span>ranges<span class="op">::</span>find<span class="op">(</span>v, <span class="dv">58</span><span class="op">)</span> <span class="op">==</span> std<span class="op">::</span>next<span class="op">(</span>v<span class="op">.</span>begin<span class="op">()))</span>;</span></code></pre></div>
<p>Some things to note here:</p>
<ul>
<li>The amount of boilerplate is very small.</li>
<li>The total amount of code is very small.</li>
<li>This abstraction allows me to concentrate on the algorithm I want to
do on the concatenated sequence, rather than the details of dealing with
boundary conditions between the underlying sequences, <em>in addition
to</em> the algorithm itself. Imagine if I had to have logic like that
found in
<code class="sourceCode default">concat_iter::operator++()</code>
<em>intermixed</em> with the algorithm code.</li>
</ul>
<p>When opportunities like this come up – that is, opportunities to
write custom iterators – the dominant consideration is what it costs to
write an iterator. If the cost is too high, we don’t write one, and the
algorithm that we would have written in terms of the unwritten iterator
becomes much more complicated (and thus error-prone). If the cost is
low, we will start to notice opportunities to write custom iterators in
many more places. One thing in particular that easy-to-write iterators
enable is easy-to-write views and view adaptors.</p>
<h2 data-number="2.3" id="iterator-adaptation"><span class="header-section-number">2.3</span> Iterator adaptation<a href="#iterator-adaptation" class="self-link"></a></h2>
<p>Sometimes, you want to take an existing iterator and adapt it for a
different use. Since you already have all the iterator operations
defined on it, it would be useful to simply use those, and fill in the
missing ones, or perhaps replace the ones that you want to work
differently.</p>
<p>For example, if we wanted to make a filtering iterator for something
like <code class="sourceCode default">filter_view</code>, we could write
it like this:</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">typename</span> Pred<span class="op">&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> filtered_int_iterator <span class="op">:</span> boost<span class="op">::</span>stl_interfaces<span class="op">::</span>iterator_interface<span class="op">&lt;</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>                                   filtered_int_iterator<span class="op">&lt;</span>Pred<span class="op">&gt;</span>,</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>                                   std<span class="op">::</span>forward_iterator_tag,</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>                                   <span class="dt">int</span><span class="op">&gt;</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    filtered_int_iterator<span class="op">()</span> <span class="op">:</span> it_<span class="op">(</span><span class="kw">nullptr</span><span class="op">)</span> <span class="op">{}</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    filtered_int_iterator<span class="op">(</span><span class="dt">int</span> <span class="op">*</span> it, <span class="dt">int</span> <span class="op">*</span> last, Pred pred<span class="op">)</span> <span class="op">:</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>        it_<span class="op">(</span>it<span class="op">)</span>,</span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>        last_<span class="op">(</span>last<span class="op">)</span>,</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>        pred_<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>pred<span class="op">))</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span> it_ <span class="op">=</span> std<span class="op">::</span>find_if<span class="op">(</span>it_, last_, pred_<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>    <span class="co">// A forward iterator based on iterator_interface usually requires</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>    <span class="co">// three user-defined operations.  since we are adapting an existing</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">// iterator (an int *), we only need to define this one.  The others are</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>    <span class="co">// implemented by iterator_interface, using the underlying int *.</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>    filtered_int_iterator <span class="op">&amp;</span> <span class="kw">operator</span><span class="op">++()</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>        it_ <span class="op">=</span> std<span class="op">::</span>find_if<span class="op">(</span>std<span class="op">::</span>next<span class="op">(</span>it_<span class="op">)</span>, last_, pred_<span class="op">)</span>;</span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a>    <span class="co">// It is really common for iterator adaptors to have a base() member</span></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a>    <span class="co">// function that returns the adapted iterator.</span></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="op">*</span> base<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> it_; <span class="op">}</span></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true" tabindex="-1"></a>    <span class="co">// Provide access to base_reference.</span></span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> boost<span class="op">::</span>stl_interfaces<span class="op">::</span>access;</span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true" tabindex="-1"></a>    <span class="co">// These functions are picked up by iterator_interface, and used to</span></span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true" tabindex="-1"></a>    <span class="co">// implement any operations that you don&#39;t define above.  They&#39;re not</span></span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true" tabindex="-1"></a>    <span class="co">// called base() so that they do not collide with the base() member above.</span></span>
<span id="cb11-35"><a href="#cb11-35" 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> base_reference<span class="op">(</span><span class="kw">this</span> <span class="kw">auto</span><span class="op">&amp;</span> self<span class="op">)</span> <span class="kw">noexcept</span></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span> <span class="cf">return</span> self<span class="op">.</span>it_; <span class="op">}</span></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="op">*</span> it_;</span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="op">*</span> last_;</span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true" tabindex="-1"></a>    Pred pred_;</span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Though this implementation is limited to
<code class="sourceCode default">int*</code>, it’s pretty easy to see
that you could change it to take an
<code class="sourceCode default">Iterator</code> template parameter
instead, and after replacing
<code class="sourceCode default">int*</code> with
<code class="sourceCode default">Iterator</code> throughout, everything
would “just work”.</p>
<h1 data-number="3" id="proposed-design"><span class="header-section-number">3</span> Proposed design<a href="#proposed-design" class="self-link"></a></h1>
<p>The proposal is to add a CRTP base template that will ease writing
iterators, in the same way that
<code class="sourceCode default">std::view_interface</code> eases the
writing of views today.</p>
<h2 data-number="3.1" id="add-iterator_interface_access"><span class="header-section-number">3.1</span> Add
<code class="sourceCode default">iterator_interface_access</code><a href="#add-iterator_interface_access" class="self-link"></a></h2>
<p>Before looking at the main
<code class="sourceCode default">iterator_interface</code> template, we
need to look at some of the bits that allow that template to function.
First,
<code class="sourceCode default">iterator_interface_access</code>.
<code class="sourceCode default">iterator_interface_access</code> is
used by the adaptation logic to get access to the underlying iterator
being adapted, which is usually private. The user just needs to friend
<code class="sourceCode default">iterator_interface_access</code> from
the iterator they write (just like the friend declaration in the
<code class="sourceCode default">filtered_int_iterator</code> example
above).</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> iterator_interface_access</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> D<span class="op">&gt;</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> base<span class="op">(</span>D<span class="op">&amp;</span> d<span class="op">)</span> <span class="kw">noexcept</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span>d<span class="op">.</span>base_reference<span class="op">())</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> d<span class="op">.</span>base_reference<span class="op">()</span>;</span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb12-9"><a href="#cb12-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> D<span class="op">&gt;</span></span>
<span id="cb12-10"><a href="#cb12-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> base<span class="op">(</span><span class="kw">const</span> D<span class="op">&amp;</span> d<span class="op">)</span> <span class="kw">noexcept</span></span>
<span id="cb12-11"><a href="#cb12-11" aria-hidden="true" tabindex="-1"></a>    <span class="op">-&gt;</span> <span class="kw">decltype</span><span class="op">(</span>d<span class="op">.</span>base_reference<span class="op">())</span></span>
<span id="cb12-12"><a href="#cb12-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">{</span></span>
<span id="cb12-13"><a href="#cb12-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> d<span class="op">.</span>base_reference<span class="op">()</span>;</span>
<span id="cb12-14"><a href="#cb12-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb12-15"><a href="#cb12-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h2 data-number="3.2" id="add-proxy_arrow_result"><span class="header-section-number">3.2</span> Add
<code class="sourceCode default">proxy_arrow_result</code><a href="#add-proxy_arrow_result" class="self-link"></a></h2>
<p>Next, <code class="sourceCode default">proxy_arrow_result</code>, a
specialization of which is used as the default
<code class="sourceCode default">pointer</code> for proxy iterators
created using the
<code class="sourceCode default">proxy_iterator_interface</code> alias
template (shown a bit later).</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> is_object_v<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> proxy_arrow_result</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> proxy_arrow_result<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> value<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">noexcept</span><span class="op">(</span>T<span class="op">(</span>value<span class="op">)))</span> <span class="op">:</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>    value_<span class="op">(</span>value<span class="op">)</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>  <span class="op">{}</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> proxy_arrow_result<span class="op">(</span>T<span class="op">&amp;&amp;</span> value<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">noexcept</span><span class="op">(</span>T<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>value<span class="op">))))</span> <span class="op">:</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>    value_<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>value<span class="op">))</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>  <span class="op">{}</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">const</span> T<span class="op">*</span> <span class="kw">operator</span><span class="op">-&gt;()</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">&amp;</span>value_; <span class="op">}</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> T<span class="op">*</span> <span class="kw">operator</span><span class="op">-&gt;()</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">&amp;</span>value_; <span class="op">}</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>  T value_;</span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h2 data-number="3.3" id="add-iterator_interface-itself"><span class="header-section-number">3.3</span> Add
<code class="sourceCode default">iterator_interface</code> itself<a href="#add-iterator_interface-itself" class="self-link"></a></h2>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> D, <span class="kw">typename</span> DifferenceType<span class="op">&gt;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em>has-plus-eq</em> <span class="op">=</span>                             <span class="co">// <em>exposition only</em></span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span>D d<span class="op">)</span> <span class="op">{</span> d <span class="op">+=</span> DifferenceType<span class="op">(</span><span class="dv">1</span><span class="op">)</span>; <span class="op">}</span>;</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Pointer, <span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> is_pointer_v<span class="op">&lt;</span>Pointer<span class="op">&gt;</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <em>make-iterator-pointer</em><span class="op">(</span>T<span class="op">&amp;&amp;</span> value<span class="op">)</span> <span class="co">// <em>exposition only</em></span></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>      <span class="op">{</span> <span class="cf">return</span> addressof<span class="op">(</span>value<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> Pointer, <span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> <em>make-iterator-pointer</em><span class="op">(</span>T<span class="op">&amp;&amp;</span> value<span class="op">)</span>             <span class="co">// <em>exposition only</em></span></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span> <span class="cf">return</span> Pointer<span class="op">(</span>std<span class="op">::</span>forward<span class="op">&lt;</span>T<span class="op">&gt;(</span>value<span class="op">))</span>; <span class="op">}</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> D,</span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> IteratorConcept,</span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> ValueType,</span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> Reference <span class="op">=</span> ValueType<span class="op">&amp;</span>,</span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> Pointer <span class="op">=</span> ValueType<span class="op">*</span>,</span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> DifferenceType <span class="op">=</span> <span class="dt">ptrdiff_t</span><span class="op">&gt;</span></span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> is_class_v<span class="op">&lt;</span>D<span class="op">&gt;</span> <span class="op">&amp;&amp;</span> same_as<span class="op">&lt;</span>D, remove_cv_t<span class="op">&lt;</span>D<span class="op">&gt;&gt;</span></span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> iterator_interface</span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb14-25"><a href="#cb14-25" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> D<span class="op">&amp;</span> derived<span class="op">()</span> <span class="kw">noexcept</span> <span class="op">{</span>              <span class="co">// <em>exposition only</em></span></span>
<span id="cb14-26"><a href="#cb14-26" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span>D<span class="op">&amp;&gt;(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb14-27"><a href="#cb14-27" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb14-28"><a href="#cb14-28" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">const</span> D<span class="op">&amp;</span> derived<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="op">{</span>  <span class="co">// <em>exposition only</em></span></span>
<span id="cb14-29"><a href="#cb14-29" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="kw">static_cast</span><span class="op">&lt;</span><span class="kw">const</span> D<span class="op">&amp;&gt;(*</span><span class="kw">this</span><span class="op">)</span>;</span>
<span id="cb14-30"><a href="#cb14-30" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb14-31"><a href="#cb14-31" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-32"><a href="#cb14-32" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb14-33"><a href="#cb14-33" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> iterator_concept <span class="op">=</span> IteratorConcept;</span>
<span id="cb14-34"><a href="#cb14-34" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> iterator_category <span class="op">=</span> iterator_concept;</span>
<span id="cb14-35"><a href="#cb14-35" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> value_type <span class="op">=</span> remove_const_t<span class="op">&lt;</span>ValueType<span class="op">&gt;</span>;</span>
<span id="cb14-36"><a href="#cb14-36" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> reference <span class="op">=</span> Reference;</span>
<span id="cb14-37"><a href="#cb14-37" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> pointer <span class="op">=</span> conditional_t<span class="op">&lt;</span></span>
<span id="cb14-38"><a href="#cb14-38" aria-hidden="true" tabindex="-1"></a>    is_same_v<span class="op">&lt;</span>iterator_concept, output_iterator_tag<span class="op">&gt;&gt;</span>,</span>
<span id="cb14-39"><a href="#cb14-39" aria-hidden="true" tabindex="-1"></a>    <span class="dt">void</span>,</span>
<span id="cb14-40"><a href="#cb14-40" aria-hidden="true" tabindex="-1"></a>    Pointer<span class="op">&gt;</span>;</span>
<span id="cb14-41"><a href="#cb14-41" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> difference_type <span class="op">=</span> DifferenceType;</span>
<span id="cb14-42"><a href="#cb14-42" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-43"><a href="#cb14-43" 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>
<span id="cb14-44"><a href="#cb14-44" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span>D d<span class="op">)</span> <span class="op">{</span> <span class="op">*</span>iterator_interface_access<span class="op">::</span>base<span class="op">(</span>d<span class="op">)</span>; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-45"><a href="#cb14-45" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">*</span>iterator_interface_access<span class="op">::</span>base<span class="op">(</span>derived<span class="op">())</span>;</span>
<span id="cb14-46"><a href="#cb14-46" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-47"><a href="#cb14-47" 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="cb14-48"><a href="#cb14-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span><span class="kw">const</span> D d<span class="op">)</span> <span class="op">{</span> <span class="op">*</span>iterator_interface_access<span class="op">::</span>base<span class="op">(</span>d<span class="op">)</span>; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-49"><a href="#cb14-49" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">*</span>iterator_interface_access<span class="op">::</span>base<span class="op">(</span>derived<span class="op">())</span>;</span>
<span id="cb14-50"><a href="#cb14-50" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-51"><a href="#cb14-51" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-52"><a href="#cb14-52" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-&gt;()</span></span>
<span id="cb14-53"><a href="#cb14-53" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span>D d<span class="op">)</span> <span class="op">{</span> <span class="op">*</span>d; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-54"><a href="#cb14-54" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <em>make-iterator-pointer</em><span class="op">&lt;</span>pointer<span class="op">&gt;(*</span>derived<span class="op">())</span>;</span>
<span id="cb14-55"><a href="#cb14-55" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-56"><a href="#cb14-56" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">-&gt;()</span> <span class="kw">const</span></span>
<span id="cb14-57"><a href="#cb14-57" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span><span class="kw">const</span> D d<span class="op">)</span> <span class="op">{</span> <span class="op">*</span>d; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-58"><a href="#cb14-58" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <em>make-iterator-pointer</em><span class="op">&lt;</span>pointer<span class="op">&gt;(*</span>derived<span class="op">())</span>;</span>
<span id="cb14-59"><a href="#cb14-59" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-60"><a href="#cb14-60" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-61"><a href="#cb14-61" 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="cb14-62"><a href="#cb14-62" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span><span class="kw">const</span> D d<span class="op">)</span> <span class="op">{</span> d <span class="op">+</span> n; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-63"><a href="#cb14-63" aria-hidden="true" tabindex="-1"></a>    D retval <span class="op">=</span> derived<span class="op">()</span>;</span>
<span id="cb14-64"><a href="#cb14-64" aria-hidden="true" tabindex="-1"></a>    retval <span class="op">+=</span> n;</span>
<span id="cb14-65"><a href="#cb14-65" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">*</span>retval;</span>
<span id="cb14-66"><a href="#cb14-66" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb14-67"><a href="#cb14-67" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-68"><a href="#cb14-68" 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>
<span id="cb14-69"><a href="#cb14-69" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span>D d<span class="op">)</span> <span class="op">{</span> <span class="op">++</span>iterator_interface_access<span class="op">::</span>base<span class="op">(</span>d<span class="op">)</span>; <span class="op">}</span> <span class="op">&amp;&amp;</span></span>
<span id="cb14-70"><a href="#cb14-70" aria-hidden="true" tabindex="-1"></a>      <span class="op">(!</span><em>has-plus-eq</em><span class="op">&lt;</span>D, difference_type<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb14-71"><a href="#cb14-71" aria-hidden="true" tabindex="-1"></a>        <span class="op">++</span>iterator_interface_access<span class="op">::</span>base<span class="op">(</span>derived<span class="op">())</span>;</span>
<span id="cb14-72"><a href="#cb14-72" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> derived<span class="op">()</span>;</span>
<span id="cb14-73"><a href="#cb14-73" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb14-74"><a href="#cb14-74" 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>
<span id="cb14-75"><a href="#cb14-75" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span>D d<span class="op">)</span> <span class="op">{</span> d <span class="op">+=</span> difference_type<span class="op">(</span><span class="dv">1</span><span class="op">)</span>; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-76"><a href="#cb14-76" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> derived<span class="op">()</span> <span class="op">+=</span> difference_type<span class="op">(</span><span class="dv">1</span><span class="op">)</span>;</span>
<span id="cb14-77"><a href="#cb14-77" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-78"><a href="#cb14-78" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">++(</span><span class="dt">int</span><span class="op">)</span> <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span>D d<span class="op">)</span> <span class="op">{</span> <span class="op">++</span>d; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-79"><a href="#cb14-79" aria-hidden="true" tabindex="-1"></a>    D retval <span class="op">=</span> derived<span class="op">()</span>;</span>
<span id="cb14-80"><a href="#cb14-80" aria-hidden="true" tabindex="-1"></a>    <span class="op">++</span>derived<span class="op">()</span>;</span>
<span id="cb14-81"><a href="#cb14-81" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> retval;</span>
<span id="cb14-82"><a href="#cb14-82" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb14-83"><a href="#cb14-83" 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>
<span id="cb14-84"><a href="#cb14-84" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span>D d<span class="op">)</span> <span class="op">{</span> iterator_interface_access<span class="op">::</span>base<span class="op">(</span>d<span class="op">)</span> <span class="op">+=</span> n; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-85"><a href="#cb14-85" aria-hidden="true" tabindex="-1"></a>      iterator_interface_access<span class="op">::</span>base<span class="op">(</span>derived<span class="op">())</span> <span class="op">+=</span> n;</span>
<span id="cb14-86"><a href="#cb14-86" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> derived<span class="op">()</span>;</span>
<span id="cb14-87"><a href="#cb14-87" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-88"><a href="#cb14-88" 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">+(</span>D it, difference_type n<span class="op">)</span></span>
<span id="cb14-89"><a href="#cb14-89" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> it <span class="op">+=</span> n; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-90"><a href="#cb14-90" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> it <span class="op">+=</span> n;</span>
<span id="cb14-91"><a href="#cb14-91" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-92"><a href="#cb14-92" 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">+(</span>difference_type n, D it<span class="op">)</span></span>
<span id="cb14-93"><a href="#cb14-93" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> it <span class="op">+=</span> n; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-94"><a href="#cb14-94" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> it <span class="op">+=</span> n;</span>
<span id="cb14-95"><a href="#cb14-95" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-96"><a href="#cb14-96" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-97"><a href="#cb14-97" 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>
<span id="cb14-98"><a href="#cb14-98" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span>D d<span class="op">)</span> <span class="op">{</span> <span class="op">--</span>iterator_interface_access<span class="op">::</span>base<span class="op">(</span>d<span class="op">)</span>; <span class="op">}</span> <span class="op">&amp;&amp;</span></span>
<span id="cb14-99"><a href="#cb14-99" aria-hidden="true" tabindex="-1"></a>      <span class="op">(!</span><em>has-plus-eq</em><span class="op">&lt;</span>D, difference_type<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb14-100"><a href="#cb14-100" aria-hidden="true" tabindex="-1"></a>        <span class="op">--</span>iterator_interface_access<span class="op">::</span>base<span class="op">(</span>derived<span class="op">())</span>;</span>
<span id="cb14-101"><a href="#cb14-101" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> derived<span class="op">()</span>;</span>
<span id="cb14-102"><a href="#cb14-102" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb14-103"><a href="#cb14-103" 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>
<span id="cb14-104"><a href="#cb14-104" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span>D d<span class="op">)</span> <span class="op">{</span> d <span class="op">+=</span> <span class="op">-</span>difference_type<span class="op">(</span><span class="dv">1</span><span class="op">)</span>; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-105"><a href="#cb14-105" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> derived<span class="op">()</span> <span class="op">+=</span> <span class="op">-</span>difference_type<span class="op">(</span><span class="dv">1</span><span class="op">)</span>;</span>
<span id="cb14-106"><a href="#cb14-106" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-107"><a href="#cb14-107" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">--(</span><span class="dt">int</span><span class="op">)</span> <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span>D d<span class="op">)</span> <span class="op">{</span> <span class="op">--</span>d; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-108"><a href="#cb14-108" aria-hidden="true" tabindex="-1"></a>    D retval <span class="op">=</span> derived<span class="op">()</span>;</span>
<span id="cb14-109"><a href="#cb14-109" aria-hidden="true" tabindex="-1"></a>    <span class="op">--</span>derived<span class="op">()</span>;</span>
<span id="cb14-110"><a href="#cb14-110" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> retval;</span>
<span id="cb14-111"><a href="#cb14-111" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb14-112"><a href="#cb14-112" 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>
<span id="cb14-113"><a href="#cb14-113" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">(</span>D d<span class="op">)</span> <span class="op">{</span> d <span class="op">+=</span> <span class="op">-</span>n; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-114"><a href="#cb14-114" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> derived<span class="op">()</span> <span class="op">+=</span> <span class="op">-</span>n;</span>
<span id="cb14-115"><a href="#cb14-115" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-116"><a href="#cb14-116" 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">-(</span>D lhs, D rhs<span class="op">)</span></span>
<span id="cb14-117"><a href="#cb14-117" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> iterator_interface_access<span class="op">::</span>base<span class="op">(</span>lhs<span class="op">)</span> <span class="op">-</span></span>
<span id="cb14-118"><a href="#cb14-118" aria-hidden="true" tabindex="-1"></a>                        iterator_interface_access<span class="op">::</span>base<span class="op">(</span>rhs<span class="op">)</span>; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-119"><a href="#cb14-119" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> iterator_interface_access<span class="op">::</span>base<span class="op">(</span>lhs<span class="op">)</span> <span class="op">-</span></span>
<span id="cb14-120"><a href="#cb14-120" aria-hidden="true" tabindex="-1"></a>             iterator_interface_access<span class="op">::</span>base<span class="op">(</span>rhs<span class="op">)</span>;</span>
<span id="cb14-121"><a href="#cb14-121" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-122"><a href="#cb14-122" 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">-(</span>D it, difference_type n<span class="op">)</span></span>
<span id="cb14-123"><a href="#cb14-123" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> it <span class="op">+=</span> <span class="op">-</span>n; <span class="op">}</span> <span class="op">{</span></span>
<span id="cb14-124"><a href="#cb14-124" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> it <span class="op">+=</span> <span class="op">-</span>n;</span>
<span id="cb14-125"><a href="#cb14-125" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-126"><a href="#cb14-126" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-127"><a href="#cb14-127" 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>D lhs, D rhs<span class="op">)</span></span>
<span id="cb14-128"><a href="#cb14-128" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> equality_comparable<span class="op">&lt;</span>D<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb14-129"><a href="#cb14-129" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">(</span>lhs <span class="op">-</span> rhs<span class="op">)</span> <span class="op">&lt;</span> <span class="kw">typename</span> D<span class="op">::</span>difference_type<span class="op">(</span><span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb14-130"><a href="#cb14-130" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-131"><a href="#cb14-131" 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>D lhs, D rhs<span class="op">)</span></span>
<span id="cb14-132"><a href="#cb14-132" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> equality_comparable<span class="op">&lt;</span>D<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb14-133"><a href="#cb14-133" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">(</span>lhs <span class="op">-</span> rhs<span class="op">)</span> <span class="op">&lt;=</span> <span class="kw">typename</span> D<span class="op">::</span>difference_type<span class="op">(</span><span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb14-134"><a href="#cb14-134" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-135"><a href="#cb14-135" 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>D lhs, D rhs<span class="op">)</span></span>
<span id="cb14-136"><a href="#cb14-136" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> equality_comparable<span class="op">&lt;</span>D<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb14-137"><a href="#cb14-137" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">(</span>lhs <span class="op">-</span> rhs<span class="op">)</span> <span class="op">&gt;</span> <span class="kw">typename</span> D<span class="op">::</span>difference_type<span class="op">(</span><span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb14-138"><a href="#cb14-138" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-139"><a href="#cb14-139" 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>D lhs, D rhs<span class="op">)</span></span>
<span id="cb14-140"><a href="#cb14-140" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> equality_comparable<span class="op">&lt;</span>D<span class="op">&gt;</span> <span class="op">{</span></span>
<span id="cb14-141"><a href="#cb14-141" aria-hidden="true" tabindex="-1"></a>      <span class="cf">return</span> <span class="op">(</span>lhs <span class="op">-</span> rhs<span class="op">)</span> <span class="op">&gt;=</span> <span class="kw">typename</span> D<span class="op">::</span>difference_type<span class="op">(</span><span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb14-142"><a href="#cb14-142" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb14-143"><a href="#cb14-143" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h2 data-number="3.4" id="add-operator-overload"><span class="header-section-number">3.4</span> Add
<code class="sourceCode default">operator==</code> overload<a href="#add-operator-overload" class="self-link"></a></h2>
<p>Additionally, we want free a
<code class="sourceCode default">operator==</code> (and
compiler-provided <code class="sourceCode default">operator!=</code>),
shown here. In addition to the constraints shown, they require that
<code class="sourceCode default">D1</code> and
<code class="sourceCode default">D2</code> are derived from
specializations of
<code class="sourceCode default">iterator_interface</code>. This is so
the overload can pick up comparisons of iterators of different, but
interoperable types (like <code class="sourceCode default">std::vector&lt;int&gt;::const_iterator</code>
and
<code class="sourceCode default">std::vector&lt;int&gt;::iterator</code>).
The full constraint is that one iterator is convertible to the other (in
either direction), and either: 1) their adapted bases are comparable; or
2) a <code class="sourceCode default">D2</code> is subtractable from a
<code class="sourceCode default">D1</code>.</p>
<p>I know those constraints look oddly specific; here’s why they are the
way they are:</p>
<p>Every category of iterator besides output need to define
<code class="sourceCode default">operator==</code>. For this reason,
each user-defined iterator derived from a specialization of
<code class="sourceCode default">iterator_interface</code> will define
its own <code class="sourceCode default">operator==</code>, unless it is
an output iterator, <em>or</em> unless it is a random access (or
contiguous) iterator. The exception for random access/contiguous is
because <code class="sourceCode default">operator-</code>, which the
user must define for a random access/contiguous iterator, can be used to
implement <code class="sourceCode default">operator==</code> – for two
iterators i1 and i2, just check if
<code class="sourceCode default">i1 - i2 == 0</code>. This explains part
of the constraints; this free overload is the implementation for
<code class="sourceCode default">operator==</code> for random
access/contiguous iterators.</p>
<p>For the base-equality-comparable part, similar logic applies: we
don’t want the user to have to define
<code class="sourceCode default">operator==</code> when the underlying
adapted iterator undoubtedly already has it (unless it’s an output
iterator, of course).</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">template</span><span class="op">&lt;</span><span class="kw">typename</span> D1, <span class="kw">typename</span> D2<span class="op">&gt;</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">concept</span> <em>base-iter-comparable</em> <span class="op">=</span>              <span class="co">// <em>exposition only</em></span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span>D1 d1, D2 d2<span class="op">)</span> <span class="op">{</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>      iterator_interface_access<span class="op">::</span>base<span class="op">(</span>d1<span class="op">)</span> <span class="op">==</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>      iterator_interface_access<span class="op">::</span>base<span class="op">(</span>d2<span class="op">)</span>;</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span>;</span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> D1, <span class="kw">typename</span> D2<span class="op">&gt;</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span>D1 lhs, D2 rhs<span class="op">)</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span> <span class="op">(</span>is_convertible_v<span class="op">&lt;</span>D2, D1<span class="op">&gt;</span> <span class="op">||</span> is_convertible_v<span class="op">&lt;</span>D1, D2<span class="op">&gt;)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb15-11"><a href="#cb15-11" aria-hidden="true" tabindex="-1"></a>             <span class="op">(</span><em>base-iter-comparable</em><span class="op">&lt;</span>D1, D2<span class="op">&gt;</span> <span class="op">||</span></span>
<span id="cb15-12"><a href="#cb15-12" aria-hidden="true" tabindex="-1"></a>              <span class="kw">requires</span> <span class="op">(</span>D1 d<span class="op">)</span> <span class="op">{</span> d <span class="op">-</span> d; <span class="op">})</span> <span class="op">{</span></span>
<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="kw">constexpr</span> <span class="op">(</span><em>base-iter-comparable</em><span class="op">&lt;</span>D1, D2<span class="op">&gt;)</span> <span class="op">{</span></span>
<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">(</span>iterator_interface_access<span class="op">::</span>base<span class="op">(</span>lhs<span class="op">)</span> <span class="op">==</span></span>
<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a>                iterator_interface_access<span class="op">::</span>base<span class="op">(</span>rhs<span class="op">))</span>;</span>
<span id="cb15-16"><a href="#cb15-16" 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><span class="kw">requires</span> <span class="op">(</span>D1 d<span class="op">)</span> <span class="op">{</span> d <span class="op">-</span> d; <span class="op">})</span> <span class="op">{</span></span>
<span id="cb15-17"><a href="#cb15-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">(</span>lhs <span class="op">-</span> rhs<span class="op">)</span> <span class="op">==</span> <span class="kw">typename</span> D1<span class="op">::</span>difference_type<span class="op">(</span><span class="dv">0</span><span class="op">)</span>;</span>
<span id="cb15-18"><a href="#cb15-18" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb15-19"><a href="#cb15-19" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span></code></pre></div>
<h2 data-number="3.5" id="add-proxy_iterator_interface"><span class="header-section-number">3.5</span> Add
<code class="sourceCode default">proxy_iterator_interface</code><a href="#add-proxy_iterator_interface" class="self-link"></a></h2>
<p>Finally, there’s an alias that makes it easier to define proxy
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><span class="kw">template</span><span class="op">&lt;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">typename</span> Derived,</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">typename</span> IteratorConcept,</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">typename</span> ValueType,</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">typename</span> Reference <span class="op">=</span> ValueType,</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">typename</span> DifferenceType <span class="op">=</span> <span class="dt">ptrdiff_t</span><span class="op">&gt;</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> proxy_iterator_interface <span class="op">=</span> iterator_interface<span class="op">&lt;</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>    Derived,</span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    IteratorConcept,</span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>    ValueType,</span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>    Reference,</span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a>    proxy_arrow_result<span class="op">&lt;</span>Reference<span class="op">&gt;</span>,</span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a>    DifferenceType<span class="op">&gt;</span>;</span></code></pre></div>
<h2 data-number="3.6" id="add-a-feature-test-macro"><span class="header-section-number">3.6</span> Add a feature test macro<a href="#add-a-feature-test-macro" class="self-link"></a></h2>
<p>Add the feature test macro
<code class="sourceCode default">__cpp_lib_iterator_interface</code>.</p>
<h2 data-number="3.7" id="design-notes"><span class="header-section-number">3.7</span> Design notes<a href="#design-notes" class="self-link"></a></h2>
<p>The template parameter <code class="sourceCode default">D</code> for
<code class="sourceCode default">iterator_interface</code> may be an
incomplete type. Before any member of the resulting specialization of
<code class="sourceCode default">iterator_interface</code> other than
special member functions is referenced,
<code class="sourceCode default">D</code> must be complete, and model
<code class="sourceCode default">std::derived_from&lt;iterator_interface&lt;D&gt;&gt;</code>.</p>
<p>Since we’re using CRTP, any operation that is provided by default
that you do not want, say because it has the wrong semantics, or because
you know of a more efficient way to do it, you can simply provided that
operation in your type, and the operation you would have inherited from
the <code class="sourceCode default">iterator_interface</code> gets
hidden.</p>
<p>I did attempt to use
<code class="sourceCode default">operator&lt;=&gt;</code> instead of the
individually-defined relational operators, but it created all kinds of
difficult-to-sort-out errors.</p>
<p>I also attempted to use deduced
<code class="sourceCode default">this</code> in
<code class="sourceCode default">iterator_interface</code>, but it did
not get rid of the need for the
<code class="sourceCode default">D</code> template parameter.
<code class="sourceCode default">D</code> is still needed to define the
hidden friend operators.</p>
<p>To get interoperability between user-created
<code class="sourceCode default">const_iterator</code> and
<code class="sourceCode default">iterator</code> types, the user must
make <code class="sourceCode default">iterator</code>s convertible to
<code class="sourceCode default">const_iterator</code>s. You can’t
automate everything.</p>
<p>Here is a handy table listing all the user-provided operations
necessary to implement all the various iterator concepts. This is every
user-defined operation, even though no one iterator requires all of
them. A following table with indicate which operations are needed when
implementing which iterator concept. In the table,
<code class="sourceCode default">Iter</code> is a user-defined type
derived from <code class="sourceCode default">iterator_interface</code>;
<code class="sourceCode default">i</code> and
<code class="sourceCode default">i2</code> are objects of type
<code class="sourceCode default">Iter</code>;
<code class="sourceCode default">reference</code> is the type passed as
the <code class="sourceCode default">Reference</code> template parameter
to <code class="sourceCode default">iterator_interface</code>;
<code class="sourceCode default">pointer</code> is the type passed as
the <code class="sourceCode default">Pointer</code> template parameter
to <code class="sourceCode default">iterator_interface</code>; and
<code class="sourceCode default">n</code> is a value of type
<code class="sourceCode default">difference_type</code>.</p>
<table>
<colgroup>
<col style="width: 6%" />
<col style="width: 17%" />
<col style="width: 31%" />
<col style="width: 44%" />
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Expression</strong>
</div></th>
<th><div style="text-align:center">
<strong>Return Type</strong>
</div></th>
<th><div style="text-align:center">
<strong>Semantics</strong>
</div></th>
<th><div style="text-align:center">
<strong>Notes</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code class="sourceCode default">*i</code></td>
<td>Convertible to
<code class="sourceCode default">reference</code>.</td>
<td>Dereferences <code class="sourceCode default">i</code> and returns
the result.</td>
<td><em>Precondition:</em> <code class="sourceCode default">i</code> is
dereferenceable.</td>
</tr>
<tr class="even">
<td><code class="sourceCode default">i == i2</code></td>
<td>Contextually convertible to
<code class="sourceCode default">bool</code>.</td>
<td>Returns true if and only if
<code class="sourceCode default">i</code> and
<code class="sourceCode default">i2</code> refer to the same value.</td>
<td><em>Precondition:</em>
<code class="sourceCode default">(i, i2)</code> is in the domain of
<code class="sourceCode default">==</code>.</td>
</tr>
<tr class="odd">
<td><code class="sourceCode default">i2 - i</code></td>
<td>Convertible to
<code class="sourceCode default">difference_type</code>.</td>
<td>Returns <code class="sourceCode default">n</code>.</td>
<td><em>Precondition:</em> there exists a value
<code class="sourceCode default">n</code> of type
<code class="sourceCode default">difference_type</code> such that
<code class="sourceCode default">i + n == i2</code>.</td>
</tr>
<tr class="even">
<td><code class="sourceCode default">++i</code></td>
<td><code class="sourceCode default">Iter &amp;</code></td>
<td>Increments <code class="sourceCode default">i</code>.</td>
<td></td>
</tr>
<tr class="odd">
<td><code class="sourceCode default">--i</code></td>
<td><code class="sourceCode default">Iter &amp;</code></td>
<td>Decrements <code class="sourceCode default">i</code>.</td>
<td></td>
</tr>
<tr class="even">
<td><code class="sourceCode default">i += n</code></td>
<td><code class="sourceCode default">Iter &amp;</code></td>
<td><code class="sourceCode default">difference_type m = n;</code><br />
<code class="sourceCode default">if (m &gt;= 0)</code><br />
    <code class="sourceCode default">while (m--) ++i;</code><br />
<code class="sourceCode default">else</code><br />
    <code class="sourceCode default">while (m++) --i;</code></td>
<td></td>
</tr>
</tbody>
</table>
<p>This table shows which user-definable operations must be defined to
meet the requirements of each of the iterator concepts.
<code class="sourceCode default">i</code>,
<code class="sourceCode default">i2</code>, and
<code class="sourceCode default">n</code> have the same meaning here as
they do in the previous table.</p>
<table>
<colgroup>
<col style="width: 64%" />
<col style="width: 35%" />
</colgroup>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Concept</strong>
</div></th>
<th><div style="text-align:center">
<strong>Operations</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code class="sourceCode default">input_iterator</code></td>
<td><code class="sourceCode default">*i</code><br />
<code class="sourceCode default">i == i2</code><br />
<code class="sourceCode default">++i</code></td>
</tr>
<tr class="even">
<td><code class="sourceCode default">output_iterator</code></td>
<td><code class="sourceCode default">*i</code><br />
<code class="sourceCode default">++i</code><br />
</td>
</tr>
<tr class="odd">
<td><code class="sourceCode default">forward_iterator</code></td>
<td><code class="sourceCode default">*i</code><br />
<code class="sourceCode default">i == i2</code><br />
<code class="sourceCode default">++i</code></td>
</tr>
<tr class="even">
<td><code class="sourceCode default">bidirectional_iterator</code></td>
<td><code class="sourceCode default">*i</code><br />
<code class="sourceCode default">i == i2</code><br />
<code class="sourceCode default">++i</code><br />
<code class="sourceCode default">--i</code></td>
</tr>
<tr class="odd">
<td><code class="sourceCode default">random_access_iterator</code>/<code class="sourceCode default">contiguous_iterator</code></td>
<td><code class="sourceCode default">*i</code><br />
<code class="sourceCode default">i - i2</code><br />
<code class="sourceCode default">i += n</code></td>
</tr>
</tbody>
</table>
<h3 data-number="3.7.1" id="nested-typedefs-in-the-dependent-base-case"><span class="header-section-number">3.7.1</span> Nested typedefs in the
dependent-base case<a href="#nested-typedefs-in-the-dependent-base-case" class="self-link"></a></h3>
<p>During the 2023-01-17 Library Evolution telecon, a question was
raised about whether the nested typedefs provided by
<code class="sourceCode default">iterator_interface</code>
(<code class="sourceCode default">iterator_category</code>, etc.) would
be defined in the derived iterator type, if the
<code class="sourceCode default">iterator_interface</code> base class
depended on a template parameter. It turns out they do, as far as I can
tell. I already had at least one such dependent-base-class type in my
unit tests for Boost.STLInterfaces, and I added another. Here is the
code:</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="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> ValueType<span class="op">&gt;</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> basic_random_access_iter_dependent</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> boost<span class="op">::</span>stl_interfaces<span class="op">::</span>iterator_interface<span class="op">&lt;</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>          basic_random_access_iter_dependent<span class="op">&lt;</span>ValueType<span class="op">&gt;</span>,</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>          std<span class="op">::</span>random_access_iterator_tag,</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>          ValueType<span class="op">&gt;</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>    basic_random_access_iter_dependent<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>    basic_random_access_iter_dependent<span class="op">(</span>ValueType <span class="op">*</span> it<span class="op">)</span> <span class="op">:</span> it_<span class="op">(</span>it<span class="op">)</span> <span class="op">{}</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>    ValueType <span class="op">&amp;</span> <span class="kw">operator</span><span class="op">*()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">*</span>it_; <span class="op">}</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>    basic_random_access_iter_dependent <span class="op">&amp;</span> <span class="kw">operator</span><span class="op">+=(</span>std<span class="op">::</span><span class="dt">ptrdiff_t</span> i<span class="op">)</span></span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>        it_ <span class="op">+=</span> i;</span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="op">*</span><span class="kw">this</span>;</span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">friend</span> std<span class="op">::</span><span class="dt">ptrdiff_t</span> <span class="kw">operator</span><span class="op">-(</span></span>
<span id="cb17-18"><a href="#cb17-18" aria-hidden="true" tabindex="-1"></a>        basic_random_access_iter_dependent lhs,</span>
<span id="cb17-19"><a href="#cb17-19" aria-hidden="true" tabindex="-1"></a>        basic_random_access_iter_dependent rhs<span class="op">)</span> <span class="kw">noexcept</span></span>
<span id="cb17-20"><a href="#cb17-20" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span></span>
<span id="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> lhs<span class="op">.</span>it_ <span class="op">-</span> rhs<span class="op">.</span>it_;</span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-24"><a href="#cb17-24" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb17-25"><a href="#cb17-25" aria-hidden="true" tabindex="-1"></a>    ValueType <span class="op">*</span> it_;</span>
<span id="cb17-26"><a href="#cb17-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb17-27"><a href="#cb17-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-28"><a href="#cb17-28" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> basic_random_access_iter_dependent_category <span class="op">=</span></span>
<span id="cb17-29"><a href="#cb17-29" aria-hidden="true" tabindex="-1"></a>    basic_random_access_iter_dependent<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;::</span>iterator_category;</span>
<span id="cb17-30"><a href="#cb17-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-31"><a href="#cb17-31" aria-hidden="true" tabindex="-1"></a>BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT<span class="op">(</span></span>
<span id="cb17-32"><a href="#cb17-32" aria-hidden="true" tabindex="-1"></a>    basic_random_access_iter_dependent<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span>, std<span class="op">::</span>random_access_iterator<span class="op">)</span></span>
<span id="cb17-33"><a href="#cb17-33" aria-hidden="true" tabindex="-1"></a>BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS<span class="op">(</span></span>
<span id="cb17-34"><a href="#cb17-34" aria-hidden="true" tabindex="-1"></a>    basic_random_access_iter_dependent<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span>,</span>
<span id="cb17-35"><a href="#cb17-35" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>random_access_iterator_tag,</span>
<span id="cb17-36"><a href="#cb17-36" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>random_access_iterator_tag,</span>
<span id="cb17-37"><a href="#cb17-37" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span>,</span>
<span id="cb17-38"><a href="#cb17-38" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="op">&amp;</span>,</span>
<span id="cb17-39"><a href="#cb17-39" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> <span class="op">*</span>,</span>
<span id="cb17-40"><a href="#cb17-40" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span><span class="dt">ptrdiff_t</span><span class="op">)</span></span></code></pre></div>
<p>This code is well-formed when built with GCC 12 in C++20 mode. The
<code class="sourceCode default">using basic_random_access_iter_dependent_category</code>
line indicates explicitly that the
<code class="sourceCode default">iterator_category</code> is visible.
The following macro lines do so implicitly – those are peace-of-mind
macros that check that your iterator meets the requirements expected by
the STL.</p>
<p>However, the names of typedefs like
<code class="sourceCode default">iterator_category</code> is unavailable
<em>inside</em> the definition of an iterator like <code class="sourceCode default">basic_random_access_iter_dependent</code>.
So, If I had used
<code class="sourceCode default">iterator_category</code> directly when
writing it, like this:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> ValueType<span class="op">&gt;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> basic_random_access_iter_dependent</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> boost<span class="op">::</span>stl_interfaces<span class="op">::</span>iterator_interface<span class="op">&lt;</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>          basic_random_access_iter_dependent<span class="op">&lt;</span>ValueType<span class="op">&gt;</span>,</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>          std<span class="op">::</span>random_access_iterator_tag,</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>          ValueType<span class="op">&gt;</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>    <span class="kw">static_assert</span><span class="op">(</span>iterator_category <span class="op">==</span> std<span class="op">::</span>random_access_iterator_tag<span class="op">)</span>;</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>    basic_random_access_iter_dependent<span class="op">()</span> <span class="op">{}</span></span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">// etc.</span></span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>… the <code class="sourceCode default">static_assert</code> would
have been ill-formed.</p>
<p>This is less-than-ideal ergonomically, but it cannot be helped by
changing the definition of
<code class="sourceCode default">iterator_interface</code>. You can work
around this shortcoming by repeating the typedefs in your derived
iterator type’s definition, or by avoiding the use of those typedefs
directly.</p>
<h3 data-number="3.7.2" id="the-name-iterator_interface"><span class="header-section-number">3.7.2</span> The name
<code class="sourceCode default">iterator_interface</code><a href="#the-name-iterator_interface" class="self-link"></a></h3>
<p>Also during the 2023-01-17 Library Evolution telecon, someone
suggested the alternate name
<code class="sourceCode default">iterator_facade</code>. I have received
no other recommendations for alternate names. LEWG may want to poll on
which of these two names it prefers.</p>
<h1 data-number="4" id="performance"><span class="header-section-number">4</span> Performance<a href="#performance" class="self-link"></a></h1>
<p>This library’s goal is not to provide high performance, so much as it
is to provide convenience – to make iterators easy to write.</p>
<p>However, this library is unlikely to have much impact on performance,
since <code class="sourceCode default">iterator_interface</code>’s
operations are all short inline functions that simply forward to a
provided operation. Optimizers are pretty good at optimizing away
function calls like that.</p>
<p>As with any performance claim, this should be verified via
measurement. Since the provided operations come from outside
<code class="sourceCode default">iterator_interface</code>, measuring
any one (or N) specializations of
<code class="sourceCode default">iterator_interface</code> will not give
the full story of all possible performance scenarios. So, I have not
tried to characterize the performance cost of using
<code class="sourceCode default">iterator_interface</code> here.</p>
<p>Users that require maximum performance should of course measure the
performance of their code that uses
<code class="sourceCode default">iterator_interface</code>, and, if it
is found wanting, reimplement their code without using
<code class="sourceCode default">iterator_interface</code>.</p>
<h1 data-number="5" id="bibliography"><span class="header-section-number">5</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-P2542R2" class="csl-entry" role="doc-biblioentry">
[P2542R2] Hui Xie, S. Levent Yilmaz. 2022-05-11. views::concat. <a href="https://wg21.link/p2542r2"><div class="csl-block">https://wg21.link/p2542r2</div></a>
</div>
</div>
</div>
</div>
</body>
</html>
