<!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-01-07" />
  <title>Conditionally safe ranges</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%;}
  </style>
  <style>
code.sourceCode > span { display: inline-block; line-height: 1.25; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
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 {
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; }

div#refs p { padding-left: 32px; text-indent: -32px; }
</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 { 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; }
div.quote {
border-left: 7px solid #ccc;
background: #f9f9f9;
margin: 1.5em 10px;
padding-left: 20px;
}
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
</style>
  <link href="data:image/vnd.microsoft.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">Conditionally safe ranges</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #: </td>
    <td>P2017R0</td>
  </tr>
  <tr>
    <td>Date: </td>
    <td>2020-01-07</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project: </td>
    <td>Programming Language C++<br>
      LWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to: </td>
    <td>
      Barry Revzin<br>&lt;<a href="mailto:barry.revzin@gmail.com" class="email">barry.revzin@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="#introduction-and-motivation"><span class="toc-section-number">1</span> Introduction and Motivation<span></span></a></li>
<li><a href="#history-and-status-quo"><span class="toc-section-number">2</span> History and Status Quo<span></span></a><ul>
<li><a href="#implementation-strategy"><span class="toc-section-number">2.1</span> Implementation Strategy<span></span></a></li>
</ul></li>
<li><a href="#proposal"><span class="toc-section-number">3</span> Proposal<span></span></a></li>
<li><a href="#wording"><span class="toc-section-number">4</span> Wording<span></span></a></li>
<li><a href="#implementation"><span class="toc-section-number">5</span> Implementation<span></span></a></li>
<li><a href="#references"><span class="toc-section-number">6</span> References<span></span></a></li>
</ul>
</div>
<h1 id="introduction-and-motivation" style="border-bottom:1px solid #cccccc"><span class="header-section-number">1</span> Introduction and Motivation<a href="#introduction-and-motivation" class="self-link"></a></h1>
<p>Consider the following approach to trimming a <code class="sourceCode cpp">std<span class="op">::</span>string</code>:</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> trim<span class="op">(</span>std<span class="op">::</span>string <span class="kw">const</span><span class="op">&amp;</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2"></a>    <span class="kw">auto</span> isalpha <span class="op">=</span> <span class="op">[](</span><span class="dt">unsigned</span> <span class="dt">char</span> c<span class="op">){</span> <span class="cf">return</span> std<span class="op">::</span>isalpha<span class="op">(</span>c<span class="op">)</span>; <span class="op">}</span>;</span>
<span id="cb1-3"><a href="#cb1-3"></a>    <span class="kw">auto</span> b <span class="op">=</span> ranges<span class="op">::</span>find_if<span class="op">(</span>s, isalpha<span class="op">)</span>;</span>
<span id="cb1-4"><a href="#cb1-4"></a>    <span class="kw">auto</span> e <span class="op">=</span> ranges<span class="op">::</span>find_if<span class="op">(</span>s <span class="op">|</span> views<span class="op">::</span>reverse, isalpha<span class="op">).</span>base<span class="op">()</span>;</span>
<span id="cb1-5"><a href="#cb1-5"></a>    <span class="cf">return</span> subrange<span class="op">(</span>b, e<span class="op">)</span>;</span>
<span id="cb1-6"><a href="#cb1-6"></a><span class="op">}</span></span></code></pre></div>
<p>This is a fairly nice and, importantly, safe way to implement <code class="sourceCode cpp">trim</code>. The iterators <code class="sourceCode cpp">b</code> and <code class="sourceCode cpp">e</code> returned from <code class="sourceCode cpp">find_if</code> will not dangle, since they point into the string <code class="sourceCode cpp">s</code> whose lifetime outlives the function.</p>
<p>Except this code will not compile at the moment, either in C++20 or in range-v3, failing on the declaration of <code class="sourceCode cpp">e</code>. The algorithm <code class="sourceCode cpp">find_if</code> is in <span>25.5.5 <a href="https://wg21.link/alg.find">[alg.find]</a></span> is declared as:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb2-2"><a href="#cb2-2"></a>         indirect_unary_predicate<span class="op">&lt;</span>projected<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span>R<span class="op">&gt;</span>, Proj<span class="op">&gt;&gt;</span> Pred<span class="op">&gt;</span></span>
<span id="cb2-3"><a href="#cb2-3"></a>  <span class="kw">constexpr</span> safe_iterator_t<span class="op">&lt;</span>R<span class="op">&gt;</span></span>
<span id="cb2-4"><a href="#cb2-4"></a>    ranges<span class="op">::</span>find_if<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, Pred pred, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span></code></pre></div>
<p><code class="sourceCode cpp">R</code> will deduce as <code class="sourceCode cpp">reverse_view<span class="op">&lt;</span>ref_view<span class="op">&lt;</span>std<span class="op">::</span>string <span class="kw">const</span><span class="op">&gt;&gt;</span></code>, which does <em>not</em> satisfy <code class="sourceCode cpp">safe_range</code> (it is neither an lvalue reference, nor does <code class="sourceCode cpp">reverse_view</code> currently opt-in to being a <code class="sourceCode cpp">safe_range</code>) hence the return type <code class="sourceCode cpp">safe_iterator_t<span class="op">&lt;</span>R<span class="op">&gt;</span></code> is the type <code class="sourceCode cpp">dangling</code> rather than being the type <code class="sourceCode cpp">iterator_t<span class="op">&lt;</span>R<span class="op">&gt;</span></code>. Instead of getting the reverse iterator we might have expected, that we need to call <code class="sourceCode cpp"><span class="op">.</span>base<span class="op">()</span></code> on, we get effectively nothing. We are forced to rewrite the above as:</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">auto</span> trim<span class="op">(</span>std<span class="op">::</span>string <span class="kw">const</span><span class="op">&amp;</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2"></a>    <span class="kw">auto</span> isalpha <span class="op">=</span> <span class="op">[](</span><span class="dt">unsigned</span> <span class="dt">char</span> c<span class="op">){</span> <span class="cf">return</span> std<span class="op">::</span>isalpha<span class="op">(</span>c<span class="op">)</span>; <span class="op">}</span>;</span>
<span id="cb3-3"><a href="#cb3-3"></a>    <span class="kw">auto</span> b <span class="op">=</span> ranges<span class="op">::</span>find_if<span class="op">(</span>s, isalpha<span class="op">)</span>;</span>
<span id="cb3-4"><a href="#cb3-4"></a>    <span class="kw">auto</span> reversed <span class="op">=</span> s <span class="op">|</span> views<span class="op">::</span>reverse;</span>
<span id="cb3-5"><a href="#cb3-5"></a>    <span class="kw">auto</span> e <span class="op">=</span> ranges<span class="op">::</span>find_if<span class="op">(</span>reversed, isalpha<span class="op">).</span>base<span class="op">()</span>;</span>
<span id="cb3-6"><a href="#cb3-6"></a>    <span class="cf">return</span> subrange<span class="op">(</span>b, e<span class="op">)</span>;</span>
<span id="cb3-7"><a href="#cb3-7"></a><span class="op">}</span></span></code></pre></div>
<p>Which is an unnecessary code indirection. The goal of this paper is to make the initial example just work. We clearly have a safe range that is not marked as such, so I consider this to be a library defect.</p>
<h1 id="history-and-status-quo" style="border-bottom:1px solid #cccccc"><span class="header-section-number">2</span> History and Status Quo<a href="#history-and-status-quo" class="self-link"></a></h1>
<p>Ranges introduced with it the concept <em><code class="sourceCode cpp">forwarding<span class="op">-</span>range</code></em>. This was then renamed to <code class="sourceCode cpp">safe_range</code> by <span class="citation" data-cites="P1870R1">[<a href="#ref-P1870R1" role="doc-biblioref">P1870R1</a>]</span> in Belfast, but the core concept remains the same. A range is a <code class="sourceCode cpp">safe_range</code> when you can safely hold onto its iterators after the range goes out of scope. There are two kinds of safe ranges:</p>
<ul>
<li>lvalue references to ranges are always safe. It’s not the lvalue reference itself which owns the data, so if the reference dies, we’re fine.</li>
<li>ranges which must necessarily opt in to being considered safe, by way of the new <code class="sourceCode cpp">enable_safe_range</code> variable template, which defaults to <code class="sourceCode cpp"><span class="kw">false</span></code> for all types.</li>
</ul>
<p>There are several safe ranges which do this opt in today:</p>
<ul>
<li><code class="sourceCode cpp">ref_view</code> is a safe_range. It’s basically a reference - the iterators it gives out are iterators to the range it refers to, which it has no ownership of. If the <code class="sourceCode cpp">ref_view</code> dies, the referred to range can still be around.</li>
<li><code class="sourceCode cpp">string_view</code> is a safe range. Like <code class="sourceCode cpp">ref_view</code>, it just refers to data - the iterators it gives out are iterators into some other containers. <code class="sourceCode cpp">span</code> and <code class="sourceCode cpp">subrange</code> are similar.</li>
<li><code class="sourceCode cpp">empty_view</code> doesn’t even have any data, so it’s trivially safe.</li>
<li><code class="sourceCode cpp">iota_view</code> works by having the iterators themselves own the “counter”, so having the iterators stick around is sufficient.</li>
</ul>
<p>And that’s it. We have six, <em>unconditionally</em> safe ranges. All other ranges and views in the standard library are <em>unconditionally</em> unsafe. But this is far too strict. As the opening example demonstrates, there are many more kinds of safe ranges you can construct than <em>just</em> the chosen six.</p>
<p>This issue was first pointed out by Johel Ernesto Guerrero Peña in <span class="citation" data-cites="stl2.640">[<a href="#ref-stl2.640" role="doc-biblioref">stl2.640</a>]</span>.</p>
<h2 id="implementation-strategy"><span class="header-section-number">2.1</span> Implementation Strategy<a href="#implementation-strategy" class="self-link"></a></h2>
<p>A range is going to be safe if its iterators do not in any way refer to it. For the ranges in the working draft which are unconditionally safe, this follows directly from how they actually work. But for some other ranges, it might depend on implementation strategy.</p>
<p>One can imagine different specifications for views like <code class="sourceCode cpp">transform_view</code> and even <code class="sourceCode cpp">filter_view</code> that might allow them to be safe, but that’s beyond the scope of this paper which is limited to those views that are already safe as specified.</p>
<h1 id="proposal" style="border-bottom:1px solid #cccccc"><span class="header-section-number">3</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>Several range adapters semantically behave as if they have a single member of some templated view type. If that underlying view type is a <code class="sourceCode cpp">safe_range</code>, the range adapter itself can be transitively safe. For example, <code class="sourceCode cpp">s <span class="op">|</span> views<span class="op">::</span>reverse</code> has the type <code class="sourceCode cpp">reverse_view<span class="op">&lt;</span>ref_view<span class="op">&lt;</span>string <span class="kw">const</span><span class="op">&gt;&gt;</span></code>. This can be a <code class="sourceCode cpp">safe_range</code> because <code class="sourceCode cpp">ref_view<span class="op">&lt;</span>string <span class="kw">const</span><span class="op">&gt;</span></code> is a <code class="sourceCode cpp">safe_range</code>. Likewise, <code class="sourceCode cpp">s <span class="op">|</span> views<span class="op">::</span>reverse <span class="op">|</span> views<span class="op">::</span>take<span class="op">(</span><span class="dv">3</span><span class="op">)</span></code> can also be a <code class="sourceCode cpp">safe_range</code> by extending this logic further.</p>
<p>Here is a table of all the range adapters and factories in the current working draft, what their current <code class="sourceCode cpp">safe_range</code> status is, and what this paper proposes.</p>
<table>
<tr>
<th>
Name
</th>
<th>
Current Status
</th>
<th>
Proposed
</th>
</tr>
<tr>
<td>
<code class="sourceCode cpp">empty</code>
</td>
<td>
Safe
</td>
<td>
No change
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">single</code>
</td>
<td>
Unsafe
</td>
<td>
No change. It’s the view which holds the element, not the iterators.
</th>
</tr>
<tr>
<td>
<code class="sourceCode cpp">iota</code>
</td>
<td>
Safe
</td>
<td>
No change.
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">istream</code>
</td>
<td>
Unsafe
</td>
<td>
No change. The iterators need to refer to parent view, which holds onto the element.
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">ref</code>
</td>
<td>
Safe
</td>
<td>
No change.
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">filter</code>
</td>
<td>
Unsafe
</td>
<td>
No change. The view needs to own the predicate.
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">transform</code>
</td>
<td>
Unsafe
</td>
<td>
No change, as above.
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">take</code>
</td>
<td>
Unsafe
</td>
<td>
<span class="addu">Conditionally safe, based on the underlying view. The iterators are just iterators into the underlying view (or thin wrappers thereof).</span>.
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">take_while</code>
</td>
<td>
Unsafe
</td>
<td>
No change, same as <code class="sourceCode cpp">filter</code>.
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">drop</code>
</td>
<td>
Unsafe
</td>
<td>
<span class="addu">Conditionally safe, same as <code class="sourceCode cpp">take</code></span>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">drop_while</code>
</td>
<td>
Unsafe
</td>
<td>
<span class="addu">Conditionally safe. Unlike <code class="sourceCode cpp">take_while</code> or <code class="sourceCode cpp">filter</code>, we only need the predicate to find the new begin. Once we found it, it’s just transparent.</span>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">join</code>
</td>
<td>
Unsafe
</td>
<td>
No change. This one is quite complex and iterators need to refer the <code class="sourceCode cpp">join_view</code>.
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">split</code>
</td>
<td>
Unsafe
</td>
<td>
No change, as with <code class="sourceCode cpp">join</code>.
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">counted</code>
</td>
<td colspan="2">
Not actually its own view, <code class="sourceCode cpp">counted<span class="op">(</span>r, n<span class="op">)</span></code> is actually either some <code class="sourceCode cpp">subrange</code> or ill-formed, so it’s already safe.
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">common</code>
</td>
<td>
Unsafe
</td>
<td>
<span class="addu">Conditionally safe based on the underlying view. All it does is propagate iterators.</span>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">reverse</code>
</td>
<td>
Unsafe
</td>
<td>
<span class="addu">Conditionally safe based on the underlying view. All it does is propagate reverse iterators.</span>
</td>
</tr>
<tr>
<td>
<code class="sourceCode cpp">elements</code>/<code class="sourceCode cpp">keys</code>/<code class="sourceCode cpp">values</code>
</td>
<td>
Unsafe
</td>
<td>
<span class="addu">Conditionally safe based on the underlying view. This is a special case of <code class="sourceCode cpp">transform_view</code> where the transform is actually encoded into the type, so it doesn’t need to be held onto by the view itself.</span>
</td>
</tr>
</table>
<h1 id="wording" style="border-bottom:1px solid #cccccc"><span class="header-section-number">4</span> Wording<a href="#wording" class="self-link"></a></h1>
<p>Add six variable template specializations to <span>24.2 <a href="https://wg21.link/ranges.syn">[ranges.syn]</a></span>:</p>
<div>
<div class="sourceCode" id="cb4"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb4-1"><a href="#cb4-1"></a>#include &lt;initializer_list&gt;</span>
<span id="cb4-2"><a href="#cb4-2"></a>#include &lt;iterator&gt;</span>
<span id="cb4-3"><a href="#cb4-3"></a></span>
<span id="cb4-4"><a href="#cb4-4"></a>namespace std::ranges {</span>
<span id="cb4-5"><a href="#cb4-5"></a>  // [...]</span>
<span id="cb4-6"><a href="#cb4-6"></a>  </span>
<span id="cb4-7"><a href="#cb4-7"></a></span>
<span id="cb4-8"><a href="#cb4-8"></a>  // [range.take], take view</span>
<span id="cb4-9"><a href="#cb4-9"></a>  template&lt;view&gt; class take_view;</span>
<span id="cb4-10"><a href="#cb4-10"></a>  </span>
<span id="cb4-11"><a href="#cb4-11"></a><span class="va">+ template&lt;class T&gt;</span></span>
<span id="cb4-12"><a href="#cb4-12"></a><span class="va">+   inline constexpr bool enable_safe_range&lt;take_view&lt;T&gt;&gt; = enable_safe_range&lt;T&gt;; </span></span>
<span id="cb4-13"><a href="#cb4-13"></a></span>
<span id="cb4-14"><a href="#cb4-14"></a>  namespace views { inline constexpr <em>unspecified</em> take = <em>unspecified</em>; }  </span>
<span id="cb4-15"><a href="#cb4-15"></a>  </span>
<span id="cb4-16"><a href="#cb4-16"></a>  // [...]</span>
<span id="cb4-17"><a href="#cb4-17"></a>  </span>
<span id="cb4-18"><a href="#cb4-18"></a>  // [range.drop], drop view</span>
<span id="cb4-19"><a href="#cb4-19"></a>  template&lt;view V&gt;</span>
<span id="cb4-20"><a href="#cb4-20"></a>    class drop_view;</span>
<span id="cb4-21"><a href="#cb4-21"></a>    </span>
<span id="cb4-22"><a href="#cb4-22"></a><span class="va">+ template&lt;class T&gt;</span></span>
<span id="cb4-23"><a href="#cb4-23"></a><span class="va">+   inline constexpr bool enable_safe_range&lt;drop_view&lt;T&gt;&gt; = enable_safe_range&lt;T&gt;; </span></span>
<span id="cb4-24"><a href="#cb4-24"></a></span>
<span id="cb4-25"><a href="#cb4-25"></a>  namespace views { inline constexpr <em>unspecified</em> drop = <em>unspecified</em>; }  </span>
<span id="cb4-26"><a href="#cb4-26"></a>  </span>
<span id="cb4-27"><a href="#cb4-27"></a>  // [range.drop.while], drop while view</span>
<span id="cb4-28"><a href="#cb4-28"></a>  template&lt;view V, class Pred&gt;</span>
<span id="cb4-29"><a href="#cb4-29"></a>    requires input_range&lt;V&gt; &amp;&amp; is_object_v&lt;Pred&gt; &amp;&amp;</span>
<span id="cb4-30"><a href="#cb4-30"></a>      indirect_unary_predicate&lt;const Pred, iterator_t&lt;V&gt;&gt;</span>
<span id="cb4-31"><a href="#cb4-31"></a>    class drop_while_view;</span>
<span id="cb4-32"><a href="#cb4-32"></a></span>
<span id="cb4-33"><a href="#cb4-33"></a><span class="va">+ template&lt;class T, class Pred&gt;</span></span>
<span id="cb4-34"><a href="#cb4-34"></a><span class="va">+   inline constexpr bool enable_safe_range&lt;drop_while_view&lt;T, Pred&gt;&gt; = enable_safe_range&lt;T&gt;; </span></span>
<span id="cb4-35"><a href="#cb4-35"></a></span>
<span id="cb4-36"><a href="#cb4-36"></a>  namespace views { inline constexpr <em>unspecified</em> drop_while = <em>unspecified</em>; }</span>
<span id="cb4-37"><a href="#cb4-37"></a></span>
<span id="cb4-38"><a href="#cb4-38"></a>  // [...]  </span>
<span id="cb4-39"><a href="#cb4-39"></a>  </span>
<span id="cb4-40"><a href="#cb4-40"></a>  // [range.common], common view</span>
<span id="cb4-41"><a href="#cb4-41"></a>  template&lt;view V&gt;</span>
<span id="cb4-42"><a href="#cb4-42"></a>    requires (!common_range&lt;V&gt; &amp;&amp; copyable&lt;iterator_t&lt;V&gt;&gt;)</span>
<span id="cb4-43"><a href="#cb4-43"></a>  class common_view;</span>
<span id="cb4-44"><a href="#cb4-44"></a>  </span>
<span id="cb4-45"><a href="#cb4-45"></a><span class="va">+ template&lt;class T&gt;</span></span>
<span id="cb4-46"><a href="#cb4-46"></a><span class="va">+   inline constexpr bool enable_safe_range&lt;common_view&lt;T&gt;&gt; = enable_safe_range&lt;T&gt;;   </span></span>
<span id="cb4-47"><a href="#cb4-47"></a></span>
<span id="cb4-48"><a href="#cb4-48"></a>  namespace views { inline constexpr <em>unspecified</em> common = <em>unspecified</em>; }</span>
<span id="cb4-49"><a href="#cb4-49"></a></span>
<span id="cb4-50"><a href="#cb4-50"></a>  // [range.reverse], reverse view</span>
<span id="cb4-51"><a href="#cb4-51"></a>  template&lt;view V&gt;</span>
<span id="cb4-52"><a href="#cb4-52"></a>    requires bidirectional_range&lt;V&gt;</span>
<span id="cb4-53"><a href="#cb4-53"></a>  class reverse_view;</span>
<span id="cb4-54"><a href="#cb4-54"></a>  </span>
<span id="cb4-55"><a href="#cb4-55"></a><span class="va">+ template&lt;class T&gt;</span></span>
<span id="cb4-56"><a href="#cb4-56"></a><span class="va">+   inline constexpr bool enable_safe_range&lt;reverse_view&lt;T&gt;&gt; = enable_safe_range&lt;T&gt;;    </span></span>
<span id="cb4-57"><a href="#cb4-57"></a></span>
<span id="cb4-58"><a href="#cb4-58"></a>  namespace views { inline constexpr <em>unspecified</em> reverse = <em>unspecified</em>; }</span>
<span id="cb4-59"><a href="#cb4-59"></a></span>
<span id="cb4-60"><a href="#cb4-60"></a>  // [range.elements], elements view</span>
<span id="cb4-61"><a href="#cb4-61"></a>  template&lt;input_range V, size_t N&gt;</span>
<span id="cb4-62"><a href="#cb4-62"></a>    requires <em>see below</em>;</span>
<span id="cb4-63"><a href="#cb4-63"></a>  class elements_view;</span>
<span id="cb4-64"><a href="#cb4-64"></a>  </span>
<span id="cb4-65"><a href="#cb4-65"></a><span class="va">+ template&lt;class T, size_t N&gt;</span></span>
<span id="cb4-66"><a href="#cb4-66"></a><span class="va">+   inline constexpr bool enable_safe_range&lt;elements_view&lt;T, N&gt;&gt; = enable_safe_range&lt;T&gt;;  </span></span>
<span id="cb4-67"><a href="#cb4-67"></a></span>
<span id="cb4-68"><a href="#cb4-68"></a>  template&lt;class R&gt;</span>
<span id="cb4-69"><a href="#cb4-69"></a>    using keys_view = elements_view&lt;all_view&lt;R&gt;, 0&gt;;</span>
<span id="cb4-70"><a href="#cb4-70"></a>  template&lt;class R&gt;</span>
<span id="cb4-71"><a href="#cb4-71"></a>    using values_view = elements_view&lt;all_view&lt;R&gt;, 1&gt;;</span>
<span id="cb4-72"><a href="#cb4-72"></a></span>
<span id="cb4-73"><a href="#cb4-73"></a>  namespace views {</span>
<span id="cb4-74"><a href="#cb4-74"></a>    template&lt;size_t N&gt;</span>
<span id="cb4-75"><a href="#cb4-75"></a>      inline constexpr <em>unspecified</em> elements = <em>unspecified</em> ;</span>
<span id="cb4-76"><a href="#cb4-76"></a>    inline constexpr <em>unspecified</em> keys = <em>unspecified</em> ;</span>
<span id="cb4-77"><a href="#cb4-77"></a>    inline constexpr <em>unspecified</em> values = <em>unspecified</em> ;</span>
<span id="cb4-78"><a href="#cb4-78"></a>  }</span>
<span id="cb4-79"><a href="#cb4-79"></a>}</span></code></pre></div>
</div>
<h1 id="implementation" style="border-bottom:1px solid #cccccc"><span class="header-section-number">5</span> Implementation<a href="#implementation" class="self-link"></a></h1>
<p>This has been implemented in range-v3 <span class="citation" data-cites="range-v3.1405">[<a href="#ref-range-v3.1405" role="doc-biblioref">range-v3.1405</a>]</span>. The PR includes the six range adapters in this paper, along with a smattering of other range adapters from range-v3 that can also be made conditionally safe in this manner (<code class="sourceCode cpp"><span class="kw">const</span></code>, <code class="sourceCode cpp">chunk</code>, <code class="sourceCode cpp">delimit</code>, <code class="sourceCode cpp">drop_exactly</code>, <code class="sourceCode cpp">indirect</code>, <code class="sourceCode cpp">intersperse</code>, <code class="sourceCode cpp">move</code>, <code class="sourceCode cpp">slice</code>, <code class="sourceCode cpp">sliding</code>, <code class="sourceCode cpp">tail</code>, <code class="sourceCode cpp">trim</code>, <code class="sourceCode cpp">unbounded</code>, and <code class="sourceCode cpp">zip</code>) as well as a bunch of other range adapters that can be additionally made conditionally safe based on both the underlying range and the shape of invocables that they rely on (<code class="sourceCode cpp">group_by</code>, all the <code class="sourceCode cpp">set_algorithm_view</code> adapters, <code class="sourceCode cpp">split_when</code>, <code class="sourceCode cpp">take_while</code>/<code class="sourceCode cpp">iter_take_while</code>, <code class="sourceCode cpp">transform</code>, and <code class="sourceCode cpp">zip_view</code>/<code class="sourceCode cpp">iter_zip_view</code>).</p>
<h1 id="references" style="border-bottom:1px solid #cccccc"><span class="header-section-number">6</span> References<a href="#references" class="self-link"></a></h1>

<div id="refs" role="doc-bibliography">
<div id="ref-P1870R1">
<p>[P1870R1] Barry Revzin. 2019. forwarding-range is too subtle. <br />
<a href="https://wg21.link/p1870r1">https://wg21.link/p1870r1</a></p>
</div>
<div id="ref-range-v3.1405">
<p>[range-v3.1405] Barry Revzin. 2020. Making more range adapters safe. <br />
<a href="https://github.com/ericniebler/range-v3/pull/1405">https://github.com/ericniebler/range-v3/pull/1405</a></p>
</div>
<div id="ref-stl2.640">
<p>[stl2.640] Johel Ernesto Guerrero Peña. 2019. Unsafe views that are actually safe. <br />
<a href="https://github.com/ericniebler/stl2/issues/640">https://github.com/ericniebler/stl2/issues/640</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
