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

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

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

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

code.sourceCode > span { display: inline; }
</style>
  <style type="text/css">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #e6ffed;
--diff-strongins: #acf2bd;
--diff-del: #ffdddd;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre, div.add blockquote { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
blockquote { background-color: #f6f8fa; }
</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">Clarifying range adaptor objects</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2281R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2021-02-19</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>
      LWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Tim Song<br>&lt;<a href="mailto:t.canens.cpp@gmail.com" class="email">t.canens.cpp@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>

</header>
<div style="clear:both">
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>This paper proposes resolutions for <span class="citation" data-cites="LWG3509">[<a href="#ref-LWG3509" role="doc-biblioref">LWG3509</a>]</span> and <span class="citation" data-cites="LWG3510">[<a href="#ref-LWG3510" role="doc-biblioref">LWG3510</a>]</span>.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="revision-history"><span class="header-section-number">2</span> Revision history<a href="#revision-history" class="self-link"></a></h1>
<ul>
<li>R1: Incorporate LWG review feedback.</li>
</ul>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="discussion"><span class="header-section-number">3</span> Discussion<a href="#discussion" class="self-link"></a></h1>
<p>The wording below clarifies that the partial application performed by range adaptor objects is essentially identical to that performed by <code class="sourceCode cpp">bind_front</code>. (Indeed, it is effectively a limited version of <code class="sourceCode cpp">bind_back</code>.) In particular, this means that the bound arguments are captured by copy or move, and never by reference. Invocation of the pipeline then either copies or moves the bound entities, depending on the value category of the pipeline.</p>
<p>In other words,</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw">auto</span> c <span class="op">=</span> <span class="co">/* some range */</span>;</span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw">auto</span> f <span class="op">=</span> <span class="co">/* expensive-to-copy function object */</span>;</span>
<span id="cb1-3"><a href="#cb1-3"></a>c <span class="op">|</span> transform<span class="op">(</span>f<span class="op">)</span>; <span class="co">// copies f and then move it into the view</span></span>
<span id="cb1-4"><a href="#cb1-4"></a></span>
<span id="cb1-5"><a href="#cb1-5"></a><span class="kw">auto</span> t <span class="op">=</span> transform<span class="op">(</span>f<span class="op">)</span>;  <span class="co">// copies f</span></span>
<span id="cb1-6"><a href="#cb1-6"></a>c <span class="op">|</span> t;  <span class="co">// copies f again from t</span></span>
<span id="cb1-7"><a href="#cb1-7"></a>c <span class="op">|</span> std<span class="op">::</span>move<span class="op">(</span>t<span class="op">)</span>; <span class="co">// moves f from t</span></span></code></pre></div>
<p>For all but one range adaptor in the standard library, the bound arguments are expected to be either function objects (which are expected to be cheap to copy and are generally copied freely) or integer-like types (which should be cheap to copy).</p>
<p><code class="sourceCode cpp">views<span class="op">::</span>split</code>, where the pattern can be a range, is an interesting case for two reasons. (The pattern can be an element as well, but that is not particularly interesting.)</p>
<ul>
<li><p>If the pattern is a C array, the decay-copy makes it into a pointer. As a result, the <code class="sourceCode cpp">split_view</code> construction might be ill-formed if the user actually meant to use the array as a range. For the most common case of string literals, using the array (including the terminating null character) as the pattern is likely unintended.</p></li>
<li><p>If the pattern is an lvalue non-view range, the copy can make it a non-viewable range when the closure object is used as an rvalue:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a>std<span class="op">::</span>string s <span class="op">=</span> <span class="st">&quot;hello&quot;</span>, s1 <span class="op">=</span> <span class="st">&quot;l&quot;</span>;</span>
<span id="cb2-2"><a href="#cb2-2"></a>views<span class="op">::</span>split<span class="op">(</span>s, s1<span class="op">)</span>;    <span class="co">// OK</span></span>
<span id="cb2-3"><a href="#cb2-3"></a>s <span class="op">|</span> views<span class="op">::</span>split<span class="op">(</span>s1<span class="op">)</span>;   <span class="co">// ill-formed under this wording; copy of s1 forwarded as rvalue</span></span>
<span id="cb2-4"><a href="#cb2-4"></a><span class="kw">auto</span> adapt <span class="op">=</span> views<span class="op">::</span>split<span class="op">(</span>s1<span class="op">)</span>;</span>
<span id="cb2-5"><a href="#cb2-5"></a>s <span class="op">|</span> adapt;              <span class="co">// OK</span></span></code></pre></div>
<p>There does not appear to be a way to avoid this without making the following function template (which demonstrates an expected use of adaptor pipelines) always return something that holds a dangling reference:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Pattern<span class="op">&gt;</span></span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="kw">auto</span> split_into_strings<span class="op">(</span>Pattern p<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3"></a>  <span class="cf">return</span> views<span class="op">::</span>split<span class="op">(</span>p<span class="op">)</span> <span class="op">|</span> views<span class="op">::</span>transform<span class="op">([](</span><span class="kw">auto</span> r<span class="op">){</span></span>
<span id="cb3-4"><a href="#cb3-4"></a>    <span class="cf">return</span> std<span class="op">::</span>string<span class="op">(</span>r<span class="op">.</span>begin<span class="op">()</span>, ranges<span class="op">::</span>next<span class="op">(</span>r<span class="op">.</span>begin<span class="op">()</span>, r<span class="op">.</span>end<span class="op">()))</span>;</span>
<span id="cb3-5"><a href="#cb3-5"></a>  <span class="op">})</span>;</span>
<span id="cb3-6"><a href="#cb3-6"></a><span class="op">}</span></span></code></pre></div></li>
</ul>
<p>In both cases, the workaround is to wrap the pattern in <code class="sourceCode cpp">views<span class="op">::</span>all</code>, which also clearly signifies the reference semantics of the capture. Having a compile-time error, while perhaps less than ideal, seems to be preferable to silent dangling.</p>
<p>As range adaptor objects are customization point objects, and the use of <code class="sourceCode cpp">bind_front</code>-like semantics means that they will be copied and invoked as non-const lvalues and possibly-const rvalues, this wording also resolves <span class="citation" data-cites="LWG3510">[<a href="#ref-LWG3510" role="doc-biblioref">LWG3510</a>]</span> by clarifying that customization point objects are invocable regardless of value category or cv-qualification.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="wording"><span class="header-section-number">4</span> Wording<a href="#wording" class="self-link"></a></h1>
<p>This wording is relative to <span class="citation" data-cites="N4878">[<a href="#ref-N4878" role="doc-biblioref">N4878</a>]</span>.</p>
<ul>
<li>Edit <span>16.3.3.3.6 <a href="https://wg21.link/customization.point.object">[customization.point.object]</a></span> as indicated:</li>
</ul>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span> All instances of a specific customization point object type shall be equal (<span>18.2 <a href="https://wg21.link/concepts.equality">[concepts.equality]</a></span>). <span class="diffins">The effects of invoking different instances of a specific customization point object type on the same arguments are equivalent.</span></p>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span> The type <code class="sourceCode cpp">T</code> of a customization point object<span class="diffins">, ignoring cv-qualifiers,</span> shall model <span class="diffins"><code class="sourceCode cpp">invocable<span class="op">&lt;</span>T<span class="op">&amp;</span>, Args<span class="op">...&gt;</span></code>,</span> <code class="sourceCode cpp">invocable<span class="op">&lt;</span><span class="kw">const</span> T<span class="op">&amp;</span>, Args<span class="op">...&gt;</span></code><span class="diffins">, <code class="sourceCode cpp">invocable<span class="op">&lt;</span>T, Args<span class="op">...&gt;</span></code>, and <code class="sourceCode cpp">invocable<span class="op">&lt;</span><span class="kw">const</span> T, Args<span class="op">...&gt;</span></code></span> (<span>18.7.2 <a href="https://wg21.link/concept.invocable">[concept.invocable]</a></span>) when the types in <code class="sourceCode cpp">Args<span class="op">...</span></code> meet the requirements specified in that customization point object’s definition. When the types of <code class="sourceCode cpp">Args<span class="op">...</span></code> do not meet the customization point object’s requirements, <code class="sourceCode cpp">T</code> shall not have a function call operator that participates in overload resolution.</p>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">5</a></span> For a given customization point object <code class="sourceCode default">o</code>, let <code class="sourceCode default">p</code> be a variable initialized as if by <code class="sourceCode default">auto p = o;</code>. Then for any sequence of arguments <code class="sourceCode default">args...</code>, the following expressions have effects equivalent to <code class="sourceCode default">o(args...)</code>:</p>
<ul>
<li><code class="sourceCode default">p(args...)</code></li>
<li><code class="sourceCode default">as_const(p)(args...)</code></li>
<li><code class="sourceCode default">std::move(p)(args...)</code></li>
<li><code class="sourceCode default">std::move(as_const(p))(args...)</code></li>
</ul>

</div>
</blockquote>
<ul>
<li>Edit <span>24.7.2 <a href="https://wg21.link/range.adaptor.object">[range.adaptor.object]</a></span> as indicated:</li>
</ul>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span> A <em>range adaptor closure object</em> is a unary function object that accepts a <code class="sourceCode cpp">viewable_­range</code> argument and returns a <code class="sourceCode cpp">view</code>. For a range adaptor closure object <code class="sourceCode cpp">C</code> and an expression <code class="sourceCode cpp">R</code> such that <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">((</span>R<span class="op">))</span></code> models <code class="sourceCode cpp">viewable_­range</code>, the following expressions are equivalent and yield a <code class="sourceCode cpp">view</code>:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a>C<span class="op">(</span>R<span class="op">)</span></span>
<span id="cb4-2"><a href="#cb4-2"></a>R <span class="op">|</span> C</span></code></pre></div>
<p>Given an additional range adaptor closure object <code class="sourceCode cpp">D</code>, the expression <code class="sourceCode cpp">C <span class="op">|</span> D</code> <span class="diffdel">is well-formed and</span> produces another range adaptor closure object <span class="diffins"><code class="sourceCode cpp">E</code>.</span> <span class="diffdel">such that the following two expressions are equivalent:</span></p>
<div class="rm" style="color: #bf0303">

<div class="sourceCode" id="cb5"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb5-1"><a href="#cb5-1"></a>R | C | D</span>
<span id="cb5-2"><a href="#cb5-2"></a>R | (C | D)</span></code></pre></div>

</div>
<div class="add" style="color: #006e28">
<p><code class="sourceCode default">E</code> is a perfect forwarding call wrapper (<span>20.14.4 <a href="https://wg21.link/func.require">[func.require]</a></span>) with the following properties:</p>
<ul>
<li>Its target object is an object <code class="sourceCode default">d</code> of type <code class="sourceCode default">decay_t&lt;decltype((D))&gt;</code> direct-non-list-initialized with <code class="sourceCode default">D</code>.</li>
<li>It has one bound argument entity, an object <code class="sourceCode default">c</code> of type <code class="sourceCode default">decay_t&lt;decltype((C))&gt;</code> direct-non-list-initialized with <code class="sourceCode default">C</code>.</li>
<li>Its call pattern is <code class="sourceCode default">d(c(arg))</code>, where <code class="sourceCode default">arg</code> is the argument used in a function call expression of <code class="sourceCode default">E</code>.</li>
</ul>
<p>The expression <code class="sourceCode default">C | D</code> is well-formed if and only if the initializations of the state entities of <code class="sourceCode default">E</code> are all well-formed.</p>
</div>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span> A <em>range adaptor object</em> is a customization point object (<span>16.3.3.3.6 <a href="https://wg21.link/customization.point.object">[customization.point.object]</a></span>) that accepts a <code class="sourceCode cpp">viewable_­range</code> as its first argument and returns a <code class="sourceCode cpp">view</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span> If a range adaptor object accepts only one argument, then it is a range adaptor closure object.</p>
<div class="rm" style="color: #bf0303">
<p><span class="marginalizedparent"><a class="marginalized">4</a></span> If a range adaptor object accepts more than one argument, then the following expressions are equivalent:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb6-1"><a href="#cb6-1"></a>adaptor(range, args...)</span>
<span id="cb6-2"><a href="#cb6-2"></a>adaptor(args...)(range)</span>
<span id="cb6-3"><a href="#cb6-3"></a>range | adaptor(args...)</span></code></pre></div>
<p>In this case, <code class="sourceCode default">adaptor(args...)</code> is a range adaptor closure object.</p>
</div>
<div class="add" style="color: #006e28">
<p><span class="marginalizedparent"><a class="marginalized">4</a></span> If a range adaptor object <code class="sourceCode default">adaptor</code> accepts more than one argument, then let <code class="sourceCode default">range</code> be an expression such that <code class="sourceCode default">decltype((range))</code> models <code class="sourceCode default">viewable_­range</code>, let <code class="sourceCode default">args...</code> be arguments such that <code class="sourceCode default">adaptor(range, args...)</code> is a well-formed expression as specified in the rest of this subclause (<span>24.7 <a href="https://wg21.link/range.adaptors">[range.adaptors]</a></span>), and let <code class="sourceCode default">BoundArgs</code> be a pack that denotes <code class="sourceCode default">decay_t&lt;decltype((args))&gt;...</code>. The expression <code class="sourceCode default">adaptor(args...)</code> produces a range adaptor closure object <code class="sourceCode default">f</code> that is a perfect forwarding call wrapper with the following properties:</p>
<ul>
<li>Its target object is a copy of <code class="sourceCode default">adaptor</code>.</li>
<li>Its bound argument entities <code class="sourceCode default">bound_args</code> consist of objects of types <code class="sourceCode default">BoundArgs...</code> direct-non-list-initialized with <code class="sourceCode default">std::forward&lt;decltype((args))&gt;(args)...</code>, respectively.</li>
<li>Its call pattern is <code class="sourceCode default">adaptor(r, bound_args...)</code>, where <code class="sourceCode default">r</code> is the argument used in a function call expression of <code class="sourceCode default">f</code>.</li>
</ul>
<p>The expression <code class="sourceCode default">adaptor(args...)</code> is well-formed if and only if the initialization of the bound argument entities of the result, as specified above, are all well-formed.</p>
</div>
</blockquote>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">5</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-LWG3509">
<p>[LWG3509] Tim Song. Range adaptor objects are underspecified. <br />
<a href="https://wg21.link/lwg3509">https://wg21.link/lwg3509</a></p>
</div>
<div id="ref-LWG3510">
<p>[LWG3510] Tim Song. Customization point objects should be invocable as non-const too. <br />
<a href="https://wg21.link/lwg3510">https://wg21.link/lwg3510</a></p>
</div>
<div id="ref-N4878">
<p>[N4878] Thomas Köppe. 2020-12-15. Working Draft, Standard for Programming Language C++. <br />
<a href="https://wg21.link/n4878">https://wg21.link/n4878</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
