<!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="2020-02-13" />
  <title>Avoid template bloat for s in combination with ‘subrange-y’ view adaptors.</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span. { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

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

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

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

code.sourceCode > span { display: inline; }
</style>
  <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">Avoid template bloat for <code class="sourceCode default">safe_range</code>s in combination with ‘subrange-y’ view adaptors.</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P1739R4</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2020-02-13</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>
      Library Working Group<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Hannes Hauswedell<br>&lt;&lt;h2 AT fsfe.org&gt;&gt;<br>
    </td>
  </tr>
</table>

</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#revision-history"><span class="toc-section-number">1</span> Revision History<span></span></a>
<ul>
<li><a href="#r4"><span class="toc-section-number">1.1</span> R4<span></span></a></li>
<li><a href="#r3"><span class="toc-section-number">1.2</span> R3<span></span></a></li>
<li><a href="#r2"><span class="toc-section-number">1.3</span> R2<span></span></a></li>
<li><a href="#r1"><span class="toc-section-number">1.4</span> R1<span></span></a></li>
<li><a href="#r0"><span class="toc-section-number">1.5</span> R0<span></span></a></li>
</ul></li>
<li><a href="#introduction"><span class="toc-section-number">2</span> Introduction<span></span></a></li>
<li><a href="#motivation-and-scope"><span class="toc-section-number">3</span> Motivation and Scope<span></span></a></li>
<li><a href="#impact-on-the-standard"><span class="toc-section-number">4</span> Impact on the Standard<span></span></a></li>
<li><a href="#design-decisions"><span class="toc-section-number">5</span> Design Decisions<span></span></a>
<ul>
<li><a href="#possible-objections-to-this-proposal"><span class="toc-section-number">5.1</span> Possible objections to this proposal<span></span></a></li>
<li><a href="#stronger-proposals"><span class="toc-section-number">5.2</span> Stronger proposals<span></span></a></li>
</ul></li>
<li><a href="#technical-specifications"><span class="toc-section-number">6</span> Technical Specifications<span></span></a>
<ul>
<li><a href="#changes-to-viewstake-range.take.overview"><span class="toc-section-number">6.1</span> Changes to <code class="sourceCode default">views::take</code> (<span>[range.take.overview]</span>):<span></span></a></li>
<li><a href="#changes-to-viewsdrop-range.drop.overview"><span class="toc-section-number">6.2</span> Changes to <code class="sourceCode default">views::drop</code> (<span>[range.drop.overview]</span>):<span></span></a></li>
<li><a href="#changes-to-viewscounted-range.counted"><span class="toc-section-number">6.3</span> Changes to <code class="sourceCode default">views::counted</code> (<span>[range.counted]</span>):<span></span></a></li>
<li><a href="#changes-to-iota_view-range.iota"><span class="toc-section-number">6.4</span> Changes to <code class="sourceCode default">iota_view</code> (<span>[range.iota]</span>):<span></span></a></li>
</ul></li>
<li><a href="#acknowledgements"><span class="toc-section-number">7</span> Acknowledgements<span></span></a></li>
<li><a href="#references"><span class="toc-section-number">8</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="revision-history" data-number="1"><span class="header-section-number">1</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<h2 data-number="1.1" id="r4" data-number="1.1"><span class="header-section-number">1.1</span> R4<a href="#r4" class="self-link"></a></h2>
<ol type="1">
<li>Rebase the wording onto <a href="https://wg21.link/n4849">N4849</a>.</li>
<li>Replace icky section numbers with stable names, which provide links to the sections of changed wording.</li>
<li>Largely rewrite wording per LWG recommendations.</li>
</ol>
<h2 data-number="1.2" id="r3" data-number="1.2"><span class="header-section-number">1.2</span> R3<a href="#r3" class="self-link"></a></h2>
<ol type="1">
<li>R2 of this paper was accepted (again) by LEWG in Belfast, but subsumed by P1664 which was also discussed in Belfast and accepted by both LEWG and LWG. P1664 was due to be voted on as Motion 14 but withdrawn before the poll.</li>
<li>The concern was that views providing “reconstructible” interfaces (e.g. construction from iterator-sentinel-pair) may still provide deviating semantics so there should be an opt-in or opt-out mechanism from the concepts.</li>
<li>Due to the very late state of the C++20 standardisation, we decided to uphold P1739 with the bare minimum of necessary changes that would otherwise be breaking. These include hard-coding the behaviour for the currently affected standard library types.</li>
<li>Any generalisation to user-defined types or the definition of concepts (P1664) is postponed to after C++20. Using an opt-in trait in the future means that none such changes would be breaking.</li>
<li>The wording changes for <code class="sourceCode default">empty_view</code> (introduction of NOP-constructor) were removed, because <code class="sourceCode default">empty_view</code> is treated separately for now. The wording changes by P1664 for <code class="sourceCode default">iota_view</code> were imported except the changes which are already adopted via P1870 (<code class="sourceCode default">safe_range</code> / <code class="sourceCode default">forwarding_range</code>).</li>
<li>The current paper is very close to the original intent and wording of P1739.</li>
</ol>
<p>Only the wording changes have been updated, not the body of the paper.</p>
<h2 data-number="1.3" id="r2" data-number="1.3"><span class="header-section-number">1.3</span> R2<a href="#r2" class="self-link"></a></h2>
<ol type="1">
<li>Change the name of the paper to reflect more accurately that no type erasure happens (in contrast to the earliest versions of this paper).</li>
<li>Updated standard references to the CD; track naming changes.</li>
<li>Provide html, because markdown isn’t rendered automatically.</li>
</ol>
<h2 data-number="1.4" id="r1" data-number="1.4"><span class="header-section-number">1.4</span> R1<a href="#r1" class="self-link"></a></h2>
<ol type="1">
<li>In the changes for <code class="sourceCode default">views::take</code> and <code class="sourceCode default">views::drop</code>, also consider constructors of the input type that take iterator and sentinel as arguments (instead of just a constructor that takes a subrange over the two). This enables us to act on such types that don’t provide the range-constructor (e.g. unclear for <code class="sourceCode default">basic_string_view</code>, in general single-argument constructors are unpopular…). If both constructors are available we prefer the (iterator, sentinel)-constructor to avoid unnecessarily instantiating the subrange-template.</li>
<li>We have added such an (iterator, sentinel)-constructor to <code class="sourceCode default">ranges::empty</code> view so that it becomes one of the types that benefit from the changes to <code class="sourceCode default">views::take</code> and <code class="sourceCode default">views::drop</code>.</li>
</ol>
<p>These changes were approved by LEWG as part of the discussion of R0 in Cologne.</p>
<h2 data-number="1.5" id="r0" data-number="1.5"><span class="header-section-number">1.5</span> R0<a href="#r0" class="self-link"></a></h2>
<p>First revision.</p>
<h1 data-number="2" id="introduction" data-number="2"><span class="header-section-number">2</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>The current draft standard introduces many range adaptor objects [24.7]. Upon invocation, most of these return a type that is specified together with the adaptor, e.g. <code class="sourceCode default">views::take</code> returns a specialization of <code class="sourceCode default">ranges::take_view</code>. Chaining multiple adaptors thus leads to an increasingly nested type. This proposal suggests avoiding nested return types when the input is a view that already represents a “subrange” and it suffices to “change the bounds”.</p>
<h1 data-number="3" id="motivation-and-scope" data-number="3"><span class="header-section-number">3</span> Motivation and Scope<a href="#motivation-and-scope" class="self-link"></a></h1>
<p>Given the following example:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a>vector vec<span class="op">{</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">5</span><span class="op">}</span>;</span>
<span id="cb1-2"><a href="#cb1-2"></a>span s<span class="op">{</span>vec<span class="op">.</span>data<span class="op">()</span>, <span class="dv">5</span><span class="op">}</span>;</span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="kw">auto</span> v <span class="op">=</span> s <span class="op">|</span> views<span class="op">::</span>drop<span class="op">(</span><span class="dv">1</span><span class="op">)</span> <span class="op">|</span> views<span class="op">::</span>take<span class="op">(</span><span class="dv">10</span><span class="op">)</span></span>
<span id="cb1-4"><a href="#cb1-4"></a>           <span class="op">|</span> views<span class="op">::</span>drop<span class="op">(</span><span class="dv">1</span><span class="op">)</span> <span class="op">|</span> views<span class="op">::</span>take<span class="op">(</span><span class="dv">10</span><span class="op">)</span>;</span></code></pre></div>
<p>The type of <code class="sourceCode default">v</code> will be something similar to</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb2-1"><a href="#cb2-1"></a>ranges::take_view&lt;ranges::drop_view&lt;ranges::take_view&lt;ranges::drop_view&lt;span&lt;int, dynamic_extent&gt; &gt; &gt; &gt; &gt;</span></code></pre></div>
<p>Although in fact it could just be <code class="sourceCode default">span&lt;int, dynamic_extent&gt;</code>, i.e. the same as the original type of <code class="sourceCode default">s</code>. This is also true for other input types that are “subrange-y” and it would feel natural to preserve the original type if only the size of the “subrange” is changed, i.e. <code class="sourceCode default">s | views::drop(1) | views::take(3)</code> should be equivalent to <code class="sourceCode default">s.subspan(1, 3)</code> if <code class="sourceCode default">s</code> is a <code class="sourceCode default">span</code>.</p>
<p>We propose that <code class="sourceCode default">views::drop</code> and <code class="sourceCode default">views::take</code> return a range of the same type as the input type (and not return a nested type) if the input is a <em>forwarding-range</em> that can be constructed from its own (adjusted) iterator and sentinel (or a <code class="sourceCode default">ranges::subrange</code> over the iterator-sentinel-pair). This includes:</p>
<ul>
<li>a <code class="sourceCode default">span</code> of dynamic extent (proposed by P1394)</li>
<li>a <code class="sourceCode default">basic_string_view</code> (proposed by P1391)</li>
<li>a <code class="sourceCode default">ranges::subrange</code> that models <code class="sourceCode default">ranges::RandomAccessRange</code> and <code class="sourceCode default">ranges::SizedRange</code></li>
<li>a <code class="sourceCode default">ranges::empty_view</code> (proposed in this paper)</li>
</ul>
<p>We also propose that the <code class="sourceCode default">views::counted</code> range factory return a <code class="sourceCode default">span</code> of dynamic extent (instead of <code class="sourceCode default">ranges::subrange</code>) if the iterator passed to it models <code class="sourceCode default">ContiguousIterator</code>.</p>
<p>The proposed changes will strongly reduce the amount of template instantiation in situations where <code class="sourceCode default">views::drop</code> and <code class="sourceCode default">views::take</code> are applied repeatedly. They increase the integration of the view machinery from <code class="sourceCode default">ranges</code> with the views created in the standard independently (<code class="sourceCode default">span</code> and <code class="sourceCode default">basic_string_view</code>). And they improve the teachability and learnability of views in general, because some of the simplest view operations now return simpler types and behave as the already documented member functions.</p>
<h1 data-number="4" id="impact-on-the-standard" data-number="4"><span class="header-section-number">4</span> Impact on the Standard<a href="#impact-on-the-standard" class="self-link"></a></h1>
<p>This proposal includes changes to the current draft standard. All proposed changes are library changes and none of the proposed changes affect the published international standard.</p>
<p>The proposal targets C++20, because applying these changes afterwards would be breaking.</p>
<p>The currently proposed wording changes depend on the following proposals:</p>
<ul>
<li><a href="https://wg21.link/p1391">P1391</a> Range constructor for <code class="sourceCode default">std::string_view</code></li>
<li><a href="https://wg21.link/p1394">P1394</a> Range constructor for <code class="sourceCode default">std::span</code></li>
</ul>
<p>Although the wording could be adapted to handle the mentioned types specifically – if the respective papers are not accepted (in time).</p>
<p><a href="https://wg21.link/p1664">P1664</a> defines concepts that this proposal could use to specify its behaviour more elegantly. It generalises the notion of <code class="sourceCode default">reconstructible-ranges</code> and makes more ranges “reconstructible” that can then benefit from the optimisations/fixes described here.</p>
<h1 data-number="5" id="design-decisions" data-number="5"><span class="header-section-number">5</span> Design Decisions<a href="#design-decisions" class="self-link"></a></h1>
<h2 data-number="5.1" id="possible-objections-to-this-proposal" data-number="5.1"><span class="header-section-number">5.1</span> Possible objections to this proposal<a href="#possible-objections-to-this-proposal" class="self-link"></a></h2>
<p>Following this proposal means that it will not hold any longer that <em>“the expression <code class="sourceCode default">views::take(E, F)</code> is expression-equivalent to <code class="sourceCode default">take_­view{E, F}</code>”</em>, i.e. the adaptor has behaviour that is distinct from the associated view class template. This may be a source of confusion, however by design of the current view machinery users are expected to interact with “the view” almost exclusively through the adaptor/factory object. And this is not the first proposal to define such specialised behaviour of an adaptor depending on its input: <a href="https://wg21.link/P1252">P1252</a> (accepted) modified <code class="sourceCode default">views::reverse</code> to “undo” the previous reversal when passed a type that already is a specialisation of <code class="sourceCode default">ranges::reverse_view</code> (instead of “applying” it a second time). The added flexibility of the adaptor approach should be seen as a feature.</p>
<p>While specialisations of e.g. <code class="sourceCode default">ranges::take_view</code> provide a <code class="sourceCode default">base()</code> member function that allows accessing the underlying range, this is not true for <code class="sourceCode default">span</code> or the other return types that we are proposing. However, since the underlying range is of the same type as the returned range, we see little value in re-transforming the range to its original type. It should also be noted that this “feature” (a <code class="sourceCode default">base()</code> member function) is provided only by some of the views in the draft standard and is not a part of the general view design. It cannot be relied on in generic contexts and combinations with other views and no parts of the standard currently make use of it.</p>
<h2 data-number="5.2" id="stronger-proposals" data-number="5.2"><span class="header-section-number">5.2</span> Stronger proposals<a href="#stronger-proposals" class="self-link"></a></h2>
<p>This proposal originally included also changing <code class="sourceCode default">views::all</code> to type-erase <code class="sourceCode default">basic_string</code> constants to <code class="sourceCode default">basic_string_view</code>; all forwarding, contiguous ranges to <code class="sourceCode default">span</code>; and all forwarding, sized, random-access ranges to <code class="sourceCode default">ranges::subrange</code>. <code class="sourceCode default">views::all</code> is the “entry-point” for all non-views in a series of view operations and normally wraps non-view-ranges in <code class="sourceCode default">ranges::ref_view</code>. Changing <code class="sourceCode default">views::all</code> in this manner would have a type-erasing effect, e.g. <code class="sourceCode default">s | views::drop(1) | views::take(3)</code> would return a <code class="sourceCode default">span</code>, independent of whether s is a <code class="sourceCode default">span</code>, a <code class="sourceCode default">vector</code> or an <code class="sourceCode default">array</code>.</p>
<p>This form of type erasure would preserve all range concepts currently defined. It is, however, possible that future more refined concepts would no longer be modelled by an input type erased in the above fashion. For this reason Casey Carter argued against changing <code class="sourceCode default">views::all</code> and it was dropped from this proposal.</p>
<p>[The current proposal does not suffer from this uncertainty, because we are preserving the exact input type and there is no erasure.]</p>
<h1 data-number="6" id="technical-specifications" data-number="6"><span class="header-section-number">6</span> Technical Specifications<a href="#technical-specifications" class="self-link"></a></h1>
<h2 data-number="6.1" id="changes-to-viewstake-range.take.overview" data-number="6.1"><span class="header-section-number">6.1</span> Changes to <code class="sourceCode default">views::take</code> (<a href="https://wg21.link/range.take.overview">[range.take.overview]</a>):<a href="#changes-to-viewstake-range.take.overview" class="self-link"></a></h2>
<div>
<div class="sourceCode" id="cb3"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb3-1"><a href="#cb3-1"></a> 2 The name views::take denotes a range adaptor object ([range.adaptor.object]).</span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="st">-  Given subexpressions E and F, the expression views::take(E, F) is expression-equivalent to take_­view{E, F}.</span></span>
<span id="cb3-3"><a href="#cb3-3"></a><span class="va">+  Let E and F be expressions, let T be remove_cvref_t&lt;decltype((E))&gt;,</span></span>
<span id="cb3-4"><a href="#cb3-4"></a><span class="va">+  and let D be range_­difference_­t&lt;decltype((E))&gt;.</span></span>
<span id="cb3-5"><a href="#cb3-5"></a><span class="va">+  If decltype((F)) does not model convertible_to&lt;D&gt;, views::take(E, F) is ill-formed.</span></span>
<span id="cb3-6"><a href="#cb3-6"></a><span class="va">+  Otherwise, the expression views::take(E, F) is expression-equivalent to:</span></span>
<span id="cb3-7"><a href="#cb3-7"></a><span class="va">+    — if T is a specialization of ranges::empty_view ([range.empty.view]), then ((void) F, <em>decay-copy</em>(E));</span></span>
<span id="cb3-8"><a href="#cb3-8"></a><span class="va">+    — otherwise, if T models random_access_range and sized_range and is</span></span>
<span id="cb3-9"><a href="#cb3-9"></a><span class="va">+      — a specialization of span ([views.span]) where T::extent == dynamic_extent,</span></span>
<span id="cb3-10"><a href="#cb3-10"></a><span class="va">+      — a specialization of basic_string_view ([string.view]),</span></span>
<span id="cb3-11"><a href="#cb3-11"></a><span class="va">+      — a specialization of ranges::iota_view ([range.iota.view]), or</span></span>
<span id="cb3-12"><a href="#cb3-12"></a><span class="va">+      — a specialization of ranges::subrange ([range.subrange]),</span></span>
<span id="cb3-13"><a href="#cb3-13"></a><span class="va">+      then T{ranges::begin(E), ranges::begin(E) + min&lt;D&gt;(ranges::size(E), F)},</span></span>
<span id="cb3-14"><a href="#cb3-14"></a><span class="va">+      except that E is evaluated only once;</span></span>
<span id="cb3-15"><a href="#cb3-15"></a><span class="va">+    — otherwise, ranges::take_­view{E, F}.</span></span></code></pre></div>
</div>
<h2 data-number="6.2" id="changes-to-viewsdrop-range.drop.overview" data-number="6.2"><span class="header-section-number">6.2</span> Changes to <code class="sourceCode default">views::drop</code> (<a href="https://wg21.link/range.drop.overview">[range.drop.overview]</a>):<a href="#changes-to-viewsdrop-range.drop.overview" class="self-link"></a></h2>
<div>
<div class="sourceCode" id="cb4"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb4-1"><a href="#cb4-1"></a> 2 The name views::drop denotes a range adaptor object ([range.adaptor.object]).</span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="st">-  Given subexpressions E and F, the expression views::drop(E, F) is expression-equivalent to drop_­view{E, F}.</span></span>
<span id="cb4-3"><a href="#cb4-3"></a><span class="va">+  Let E and F be expressions, let T be remove_cvref_t&lt;decltype((E))&gt;,</span></span>
<span id="cb4-4"><a href="#cb4-4"></a><span class="va">+  and let D be range_­difference_­t&lt;decltype((E))&gt;.</span></span>
<span id="cb4-5"><a href="#cb4-5"></a><span class="va">+  If decltype((F)) does not model convertible_to&lt;D&gt;, views::drop(E, F) is ill-formed.</span></span>
<span id="cb4-6"><a href="#cb4-6"></a><span class="va">+  Otherwise, the expression views::drop(E, F) is expression-equivalent to:</span></span>
<span id="cb4-7"><a href="#cb4-7"></a><span class="va">+    — if T is a specialization of ranges::empty_view ([range.empty.view]), then ((void) F, <em>decay-copy</em>(E));</span></span>
<span id="cb4-8"><a href="#cb4-8"></a><span class="va">+    — otherwise, if T models random_access_range and sized_range and is</span></span>
<span id="cb4-9"><a href="#cb4-9"></a><span class="va">+      — a specialization of span ([views.span]) where T::extent == dynamic_extent,</span></span>
<span id="cb4-10"><a href="#cb4-10"></a><span class="va">+      — a specialization of basic_string_view ([string.view]),</span></span>
<span id="cb4-11"><a href="#cb4-11"></a><span class="va">+      — a specialization of ranges::iota_view ([range.iota.view]), or</span></span>
<span id="cb4-12"><a href="#cb4-12"></a><span class="va">+      — a specialization of ranges::subrange ([range.subrange]),</span></span>
<span id="cb4-13"><a href="#cb4-13"></a><span class="va">+      then T{ranges::begin(E) + min&lt;D&gt;(ranges::size(E), F), ranges::end(E)},</span></span>
<span id="cb4-14"><a href="#cb4-14"></a><span class="va">+      except that E is evaluated only once;</span></span>
<span id="cb4-15"><a href="#cb4-15"></a><span class="va">+    — otherwise, ranges::drop_­view{E, F}.</span></span></code></pre></div>
</div>
<h2 data-number="6.3" id="changes-to-viewscounted-range.counted" data-number="6.3"><span class="header-section-number">6.3</span> Changes to <code class="sourceCode default">views::counted</code> (<a href="https://wg21.link/range.counted">[range.counted]</a>):<a href="#changes-to-viewscounted-range.counted" class="self-link"></a></h2>
<div>
<div class="sourceCode" id="cb5"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb5-1"><a href="#cb5-1"></a> 2 The name views::counted denotes a customization point object ([customization.point.object]).</span>
<span id="cb5-2"><a href="#cb5-2"></a><span class="st">-  Let E and F be expressions, and let T be decay_­t&lt;decltype((E))&gt;.</span></span>
<span id="cb5-3"><a href="#cb5-3"></a><span class="st">-  Then the expression views::counted(E, F) is expression-equivalent to:</span></span>
<span id="cb5-4"><a href="#cb5-4"></a><span class="st">-  — If T models input_or_output_iterator and decltype((F)) models convertible_to&lt;iter_­difference_­t&lt;T&gt;&gt;,</span></span>
<span id="cb5-5"><a href="#cb5-5"></a><span class="st">-    — subrange{E, E + static_­cast&lt;iter_­difference_­t&lt;T&gt;&gt;(F)} if T models random_access_iterator.</span></span>
<span id="cb5-6"><a href="#cb5-6"></a><span class="st">-  — Otherwise, subrange{counted_­iterator{E, F}, default_­sentinel}.</span></span>
<span id="cb5-7"><a href="#cb5-7"></a><span class="st">-  — Otherwise, views::counted(E, F) is ill-formed.</span></span>
<span id="cb5-8"><a href="#cb5-8"></a><span class="va">+  Let E and F be expressions, let T be decay_­t&lt;decltype((E))&gt;,</span></span>
<span id="cb5-9"><a href="#cb5-9"></a><span class="va">+  and let D be iter_­difference_­t&lt;T&gt;.</span></span>
<span id="cb5-10"><a href="#cb5-10"></a><span class="va">+  If decltype((F)) does not model convertible_to&lt;D&gt;, views::counted(E, F) is ill-formed.</span></span>
<span id="cb5-11"><a href="#cb5-11"></a><span class="va">+  otherwise, views::counted(E, F) is expression-equivalent to:</span></span>
<span id="cb5-12"><a href="#cb5-12"></a><span class="va">+  — if T models contiguous_iterator, then span{to_address(E), static_­cast&lt;D&gt;(F)};</span></span>
<span id="cb5-13"><a href="#cb5-13"></a><span class="va">+  — otherwise, if T models random_access_iterator, then</span></span>
<span id="cb5-14"><a href="#cb5-14"></a><span class="va">+    subrange{E, E + static_­cast&lt;D&gt;(F)}, except that E is evaluated only once;</span></span>
<span id="cb5-15"><a href="#cb5-15"></a><span class="va">+  — otherwise, subrange{counted_­iterator{E, F}, default_­sentinel}.</span></span></code></pre></div>
</div>
<h2 data-number="6.4" id="changes-to-iota_view-range.iota" data-number="6.4"><span class="header-section-number">6.4</span> Changes to <code class="sourceCode default">iota_view</code> (<a href="https://wg21.link/range.iota">[range.iota]</a>):<a href="#changes-to-iota_view-range.iota" class="self-link"></a></h2>
<p>The following changes make <code class="sourceCode default">ranges::iota_view</code> constructible from its iterator-sentinel-pair.</p>
<p>In <a href="https://wg21.link/range.iota.view">[range.iota.view]</a>:</p>
<div>
<div class="sourceCode" id="cb6"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb6-1"><a href="#cb6-1"></a> [...]</span>
<span id="cb6-2"><a href="#cb6-2"></a> iota_view() = default;</span>
<span id="cb6-3"><a href="#cb6-3"></a> constexpr explicit iota_view(W value);</span>
<span id="cb6-4"><a href="#cb6-4"></a> constexpr iota_view(type_identity_t&lt;W&gt; value,</span>
<span id="cb6-5"><a href="#cb6-5"></a>                     type_identity_t&lt;Bound&gt; bound);</span>
<span id="cb6-6"><a href="#cb6-6"></a></span>
<span id="cb6-7"><a href="#cb6-7"></a><span class="va">+constexpr iota_view(iterator first, sentinel last) : iota_view(*first, last.bound_) {}</span></span>
<span id="cb6-8"><a href="#cb6-8"></a></span>
<span id="cb6-9"><a href="#cb6-9"></a> constexpr iterator begin() const;</span>
<span id="cb6-10"><a href="#cb6-10"></a> constexpr auto end() const;</span>
<span id="cb6-11"><a href="#cb6-11"></a> constexpr iterator end() const requires same_as&lt;W, Bound&gt;;</span>
<span id="cb6-12"><a href="#cb6-12"></a> [...]</span></code></pre></div>
</div>
<h1 data-number="7" id="acknowledgements" data-number="7"><span class="header-section-number">7</span> Acknowledgements<a href="#acknowledgements" class="self-link"></a></h1>
<p>Thanks to Casey Carter, Eric Niebler, Barry Revzin and Corentin Jabot for feedback on the proposal. Many thanks to JeanHeyd Meneide for alerting me to and involving me in P1664 which would solve some of the things described here more elegantly (and more generically). An extra-special thanks to Casey for incorporating LWG’s recommended wording changes, a bit of redrafting, and generally getting this proposal across the goal line.</p>
<h1 data-number="8" id="references" data-number="8"><span class="header-section-number">8</span> References<a href="#references" class="self-link"></a></h1>
<ul>
<li><a href="https://wg21.link/p1035">P1035</a> Input range adaptors</li>
<li><a href="https://wg21.link/P1252">P1252</a> Ranges Design Cleanup</li>
<li><a href="https://wg21.link/p1391">P1391</a> Range constructor for <code class="sourceCode default">std::string_view</code></li>
<li><a href="https://wg21.link/p1394">P1394</a> Range constructor for <code class="sourceCode default">std::span</code></li>
<li><a href="https://wg21.link/p1664">P1664</a> Reconstructible Ranges</li>
</ul>
</div>
</div>
</body>
</html>
