<!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-10" />
  <title>starts\_with and ends\_with</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">starts_with and ends_with</h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P1659R2</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2021-02-10</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 Wording<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Christopher Di Bella<br>&lt;<a href="mailto:cjdb.ns@gmail.com" class="email">cjdb.ns@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="#abstract"><span class="toc-section-number">1</span> Abstract<span></span></a></li>
<li><a href="#change-log"><span class="toc-section-number">2</span> Change log<span></span></a>
<ul>
<li><a href="#r1-r2"><span class="toc-section-number">2.1</span> R1 → R2<span></span></a></li>
<li><a href="#r0-r1"><span class="toc-section-number">2.2</span> R0 → R1<span></span></a></li>
</ul></li>
<li><a href="#motivation"><span class="toc-section-number">3</span> Motivation<span></span></a>
<ul>
<li><a href="#example-usage"><span class="toc-section-number">3.1</span> Example usage<span></span></a></li>
</ul></li>
<li><a href="#proposed-changes-to-sd-8"><span class="toc-section-number">4</span> Proposed changes to SD-8<span></span></a></li>
<li><a href="#proposed-changes-to-c23"><span class="toc-section-number">5</span> Proposed changes to C++23<span></span></a>
<ul>
<li><a href="#starts-with-alg.starts.with"><span class="toc-section-number">5.1</span> 25.6.14 Starts with [alg.starts.with]<span></span></a></li>
<li><a href="#ends-with-alg.ends.with"><span class="toc-section-number">5.2</span> 25.6.15 Ends with [alg.ends.with]<span></span></a></li>
</ul></li>
<li><a href="#reference-implementation"><span class="toc-section-number">6</span> Reference implementation<span></span></a></li>
<li><a href="#acknowledgements"><span class="toc-section-number">7</span> Acknowledgements<span></span></a></li>
<li><a href="#bibliography"><span class="toc-section-number">8</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>This proposal seeks to add <code class="sourceCode default">std::ranges::starts_with</code> and <code class="sourceCode default">std::ranges::ends_with</code>, which would work on arbitrary ranges, and also answer questions such as “are the starting elements of <code class="sourceCode default">r1</code> <em>less than</em> the elements of <code class="sourceCode default">r2</code>?” and “are the final elements of <code class="sourceCode default">r1</code> <em>greater than</em> the elements of <code class="sourceCode default">r2</code>?”. It also proposes a change to SD-8.</p>
<h1 data-number="2" id="change-log"><span class="header-section-number">2</span> Change log<a href="#change-log" class="self-link"></a></h1>
<h2 data-number="2.1" id="r1-r2"><span class="header-section-number">2.1</span> R1 → R2<a href="#r1-r2" class="self-link"></a></h2>
<ul>
<li>Replaces <em>Effects</em> with <em>Returns</em>.</li>
</ul>
<h2 data-number="2.2" id="r0-r1"><span class="header-section-number">2.2</span> R0 → R1<a href="#r0-r1" class="self-link"></a></h2>
<ul>
<li>New document layout.</li>
<li>Adds feature test macro.</li>
<li>Replaces <code class="sourceCode default">PascalCase</code> concept names with <code class="sourceCode default">snake_case</code> concept names.</li>
<li>Renames <code class="sourceCode default">Comp</code> to <code class="sourceCode default">Pred</code>.</li>
<li>Removes paragraph 2 from [alg.starts_with].</li>
</ul>
<h1 data-number="3" id="motivation"><span class="header-section-number">3</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>C++20 introduces <code class="sourceCode default">basic_string_view::starts_with</code>, <code class="sourceCode default">basic_string_view::ends_with</code>, <code class="sourceCode default">basic_string::starts_with</code>, and <code class="sourceCode default">basic_string::ends_with</code>. Both <code class="sourceCode default">basic_string</code> and <code class="sourceCode default">basic_string_view</code> are perculiar container-like types, with many member functions that duplicate algorithm functionality with minor interface changes (e.g. <code class="sourceCode default">compare</code>, <code class="sourceCode default">copy</code>, <code class="sourceCode default">find</code>, <code class="sourceCode default">rfind</code>, <code class="sourceCode default">find_first_of</code>, etc.). <span class="citation" data-cites="P0457R2">[<a href="#ref-P0457R2" role="doc-biblioref">P0457R2</a>]</span> §5.1 notes that the decision to add <code class="sourceCode default">starts_with</code> and <code class="sourceCode default">ends_with</code> as member functions was because (a) it is consistent with the aforementioned member functions, and (b) that P0457 agrees with <span class="citation" data-cites="N3609">[<a href="#ref-N3609" role="doc-biblioref">N3609</a>]</span> in that <code class="sourceCode default">starts_with(haystack, needle)</code> is ambiguous with <code class="sourceCode default">starts_with(needle, haystack)</code>. It should be noted that neither N3609, nor P0457 identified whether or not they were talking about non-member functions that only operate on string types, or if they were discussing an algorithm, but the LEWG minutes for P0457 reveal some LWEG interest in making them algorithms.</p>
<p>Although there is prior art with respect to <code class="sourceCode default">basic_string</code>’s member functions, the author expresses concern that our string types have a large set of member functions that either duplicate the algorithms or are directly incompatible with them, and thus limit the amount of composition that’s possible. Templates are one of C++’s greatest strengths, and with iterators, we have an extremely extensible and powerful generic programming model. We should take advantage of this model wherever possible to ensure that we do not paint ourselves into a corner with a single type.</p>
<p>At present, it isn’t <em>immediately</em> possible to query whether or not any range – other than a standard string type – is prefixed or suffixed by another range. To do so, one must use <code class="sourceCode default">mismatch</code> or <code class="sourceCode default">equal</code>, and at least in the case of <code class="sourceCode default">ends_with</code>, <code class="sourceCode default">ranges::next</code> (C++20).</p>
<p>It is interesting to note that, since <code class="sourceCode default">starts_with</code> and <code class="sourceCode default">ends_with</code> can be implemented using <code class="sourceCode default">mismatch</code>, we are able to query more than just “are the first <em>n</em> elements of range one the same as the entirety of range two?”: we’re also able to query “are the first <em>n</em> elements of range one all greater than the entirety of range two?”, where <em>n</em> is the distance of the second range. See §1.1 for examples. This is something that the string-based member functions are not able to do, although the author acknowledges that text processing may not require this functionality.</p>
<p>Concerns were outlined in both N3609 and P0457 about the ambiguity of whether we are performing <code class="sourceCode default">starts_with(haystack, needle)</code> or <code class="sourceCode default">starts_with(needle, haystack)</code>. There is prior art in the algorithms library that makes the first range the subject of the operation: <code class="sourceCode default">mismatch</code>, <code class="sourceCode default">equal</code>, <code class="sourceCode default">search</code>, <code class="sourceCode default">find_first_of</code>, and <code class="sourceCode default">lexicographical_compare</code> all take the form <code class="sourceCode default">algorithm(haystack, needle)</code>, so the author remains unconvinced about the ambiguity.</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div 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> some_ints <span class="op">=</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">50</span><span class="op">)</span>;</span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw">auto</span> some_more_ints <span class="op">=</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">30</span><span class="op">)</span>;</span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="cf">if</span> <span class="op">(</span>ranges<span class="op">::</span>mismatch<span class="op">(</span>some_ints, some_more_ints<span class="op">).</span>in2 <span class="op">==</span> end<span class="op">(</span>some_more_ints<span class="op">))</span> <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4"></a>   <span class="co">// do something</span></span>
<span id="cb1-5"><a href="#cb1-5"></a><span class="op">}</span></span></code></pre></div></td>
<td><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">auto</span> some_ints <span class="op">=</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">50</span><span class="op">)</span>;</span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="kw">auto</span> some_more_ints <span class="op">=</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">30</span><span class="op">)</span>;</span>
<span id="cb2-3"><a href="#cb2-3"></a><span class="cf">if</span> <span class="op">(</span>ranges<span class="op">::</span>starts_with<span class="op">(</span>some_ints, some_more_ints<span class="op">))</span> <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4"></a>   <span class="co">// do something</span></span>
<span id="cb2-5"><a href="#cb2-5"></a><span class="op">}</span></span></code></pre></div></td>
</tr>
<tr class="even">
<td><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> some_ints <span class="op">=</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">50</span><span class="op">)</span>;</span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="kw">auto</span> some_more_ints <span class="op">=</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">30</span><span class="op">)</span>;</span>
<span id="cb3-3"><a href="#cb3-3"></a><span class="op">{</span></span>
<span id="cb3-4"><a href="#cb3-4"></a>   <span class="kw">auto</span> some_ints_tail <span class="op">=</span> subrange<span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5"></a>     next<span class="op">(</span>begin<span class="op">(</span>some_ints<span class="op">)</span>, distance<span class="op">(</span>some_more_ints<span class="op">)</span>, end<span class="op">(</span>some_ints<span class="op">))</span>,</span>
<span id="cb3-6"><a href="#cb3-6"></a>     end<span class="op">(</span>some_ints<span class="op">)</span></span>
<span id="cb3-7"><a href="#cb3-7"></a>   <span class="op">}</span>;</span>
<span id="cb3-8"><a href="#cb3-8"></a>   <span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> equal<span class="op">(</span>some_ints_tail, some_more_ints<span class="op">))</span> <span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9"></a>      <span class="co">// do something</span></span>
<span id="cb3-10"><a href="#cb3-10"></a>   <span class="op">}</span></span>
<span id="cb3-11"><a href="#cb3-11"></a><span class="op">}</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="kw">auto</span> some_ints <span class="op">=</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">50</span><span class="op">)</span>;</span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="kw">auto</span> some_more_ints <span class="op">=</span> view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">30</span><span class="op">)</span>;</span>
<span id="cb4-3"><a href="#cb4-3"></a><span class="cf">if</span> <span class="op">(</span><span class="kw">not</span> ranges<span class="op">::</span>ends_with<span class="op">(</span>some_ints, some_more_ints<span class="op">))</span> <span class="op">{</span></span>
<span id="cb4-4"><a href="#cb4-4"></a>   <span class="co">// do something</span></span>
<span id="cb4-5"><a href="#cb4-5"></a><span class="op">}</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<h2 data-number="3.1" id="example-usage"><span class="header-section-number">3.1</span> Example usage<a href="#example-usage" class="self-link"></a></h2>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="kw">auto</span> script <span class="op">=</span> <span class="st">u8&quot;OBI-WAN: Hello, there!</span><span class="sc">\n</span><span class="st">&quot;</span></span>
<span id="cb5-2"><a href="#cb5-2"></a>              <span class="st">u8&quot;GENERAL GRIEVOUS: General Kenobi, you are a bold one.&quot;</span><span class="bu">sv</span>;</span>
<span id="cb5-3"><a href="#cb5-3"></a><span class="kw">namespace</span> ranges <span class="op">=</span> std<span class="op">::</span>ranges;</span>
<span id="cb5-4"><a href="#cb5-4"></a>ranges<span class="op">::</span>starts_with<span class="op">(</span>script, <span class="st">u8&quot;OBI-WAN&quot;</span><span class="bu">sv</span><span class="op">)</span>;               <span class="co">// returns true</span></span>
<span id="cb5-5"><a href="#cb5-5"></a>ranges<span class="op">::</span>starts_with<span class="op">(</span>script, <span class="st">u8&quot;ABCDEFG&quot;</span><span class="bu">sv</span><span class="op">)</span>;               <span class="co">// returns false</span></span>
<span id="cb5-6"><a href="#cb5-6"></a>ranges<span class="op">::</span>starts_with<span class="op">(</span>script, <span class="st">u8&quot;ABCDEFG&quot;</span><span class="bu">sv</span>, ranges<span class="op">::</span>less<span class="op">)</span>; <span class="co">// returns true</span></span>
<span id="cb5-7"><a href="#cb5-7"></a></span>
<span id="cb5-8"><a href="#cb5-8"></a><span class="kw">namespace</span> view <span class="op">=</span> ranges<span class="op">::</span>view;</span>
<span id="cb5-9"><a href="#cb5-9"></a>ranges<span class="op">::</span>ends_with<span class="op">(</span>view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">50</span><span class="op">)</span>, view<span class="op">::</span>iota<span class="op">(</span><span class="dv">30</span><span class="op">)</span> <span class="op">|</span> view<span class="op">::</span>take<span class="op">(</span><span class="dv">20</span><span class="op">))</span>;       <span class="co">// returns true</span></span>
<span id="cb5-10"><a href="#cb5-10"></a>ranges<span class="op">::</span>ends_with<span class="op">(</span>view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">50</span><span class="op">)</span>, view<span class="op">::</span>iota<span class="op">(</span><span class="dv">30</span><span class="op">)</span> <span class="op">|</span> view<span class="op">::</span>take<span class="op">(</span><span class="dv">50</span><span class="op">))</span>;       <span class="co">// returns false</span></span>
<span id="cb5-11"><a href="#cb5-11"></a>ranges<span class="op">::</span>ends_with<span class="op">(</span>view<span class="op">::</span>iota<span class="op">(</span><span class="dv">0</span>, <span class="dv">50</span><span class="op">)</span>, view<span class="op">::</span>iota<span class="op">(-</span><span class="dv">50</span>, <span class="op">-</span><span class="dv">40</span><span class="op">)</span>, ranges<span class="op">::</span>greater<span class="op">)</span>; <span class="co">// returns true</span></span></code></pre></div>
<h1 data-number="4" id="proposed-changes-to-sd-8"><span class="header-section-number">4</span> Proposed changes to SD-8<a href="#proposed-changes-to-sd-8" class="self-link"></a></h1>
<p>In response to the concerns outlined in the motivation section of this document, the author would like to request that LEWG consider discussing adopting in SD-8, a policy of ensuring that options for algorithms are preferred when a proposal to add a member function to a container-like type is considered.</p>
<h1 data-number="5" id="proposed-changes-to-c23"><span class="header-section-number">5</span> Proposed changes to C++23<a href="#proposed-changes-to-c23" class="self-link"></a></h1>
<p>Add the following to <span>17.3.2
 <a href="https://wg21.link/version.syn">[version.syn]</a></span>:</p>
<div>
<div class="sourceCode" id="cb6"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb6-1"><a href="#cb6-1"></a>#define __cpp_lib_ranges_starts_ends_with 202007L // also in &lt;algorithm&gt;</span></code></pre></div>
</div>
<p>Add the following text to <span>25.4
 <a href="https://wg21.link/algorithm.syn">[algorithm.syn]</a></span>:</p>
<div>
<div class="sourceCode" id="cb7"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb7-1"><a href="#cb7-1"></a>...</span>
<span id="cb7-2"><a href="#cb7-2"></a>template&lt;class forward_iterator, class Searcher&gt;</span>
<span id="cb7-3"><a href="#cb7-3"></a>  constexpr forward_iterator</span>
<span id="cb7-4"><a href="#cb7-4"></a>    search(forward_iterator first, forward_iterator last, const Searcher&amp; searcher);</span>
<span id="cb7-5"><a href="#cb7-5"></a></span>
<span id="cb7-6"><a href="#cb7-6"></a><span class="va">+ // [alg.starts_with], starts_with</span></span>
<span id="cb7-7"><a href="#cb7-7"></a><span class="va">+ template&lt;input_iterator I1, sentinel_for&lt;I1&gt; S1, input_iterator I2, sentinel_for&lt;I2&gt; S2,</span></span>
<span id="cb7-8"><a href="#cb7-8"></a><span class="va">+          class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity&gt;</span></span>
<span id="cb7-9"><a href="#cb7-9"></a><span class="va">+   requires indirectly_comparable&lt;I1, I2, Pred, Proj1, Proj2&gt;</span></span>
<span id="cb7-10"><a href="#cb7-10"></a><span class="va">+ constexpr bool ranges::starts_with(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},</span></span>
<span id="cb7-11"><a href="#cb7-11"></a><span class="va">+                                    Proj1 proj1 = {}, Proj2 proj2 = {});</span></span>
<span id="cb7-12"><a href="#cb7-12"></a><span class="va">+ template&lt;input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity,</span></span>
<span id="cb7-13"><a href="#cb7-13"></a><span class="va">+          class Proj2 = identity&gt;</span></span>
<span id="cb7-14"><a href="#cb7-14"></a><span class="va">+   requires indirectly_comparable&lt;iterator_t&lt;R1&gt;, iterator_t&lt;R2&gt;, Pred, Proj1, Proj2&gt;</span></span>
<span id="cb7-15"><a href="#cb7-15"></a><span class="va">+ constexpr bool ranges::starts_with(R1&amp;&amp; r1, R2&amp;&amp; r2, Pred pred = {},</span></span>
<span id="cb7-16"><a href="#cb7-16"></a><span class="va">+                                    Proj1 proj1 = {}, Proj2 proj2 = {});</span></span>
<span id="cb7-17"><a href="#cb7-17"></a><span class="va">+</span></span>
<span id="cb7-18"><a href="#cb7-18"></a><span class="va">+ // [alg.ends_with], ends_with</span></span>
<span id="cb7-19"><a href="#cb7-19"></a><span class="va">+ template&lt;input_iterator I1, sentinel_for&lt;I1&gt; S1, input_iterator I2, sentinel_for&lt;I2&gt; S2,</span></span>
<span id="cb7-20"><a href="#cb7-20"></a><span class="va">+          class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity&gt;</span></span>
<span id="cb7-21"><a href="#cb7-21"></a><span class="va">+   requires (forward_iterator&lt;I1&gt; || sized_sentinel_for&lt;S1, I1&gt;) &amp;&amp;</span></span>
<span id="cb7-22"><a href="#cb7-22"></a><span class="va">+            (forward_iterator&lt;I2&gt; || sized_sentinel_for&lt;S2, I2&gt;) &amp;&amp;</span></span>
<span id="cb7-23"><a href="#cb7-23"></a><span class="va">+            indirectly_comparable&lt;I1, I2, Pred, Proj1, Proj2&gt;</span></span>
<span id="cb7-24"><a href="#cb7-24"></a><span class="va">+ constexpr bool ranges::ends_with(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},</span></span>
<span id="cb7-25"><a href="#cb7-25"></a><span class="va">+                                  Proj1 proj1 = {}, Proj2 proj2 = {});</span></span>
<span id="cb7-26"><a href="#cb7-26"></a><span class="va">+ template&lt;input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity,</span></span>
<span id="cb7-27"><a href="#cb7-27"></a><span class="va">+          class Proj2 = identity&gt;</span></span>
<span id="cb7-28"><a href="#cb7-28"></a><span class="va">+   requires (forward_range&lt;R1&gt; || sized_range&lt;R1&gt;) &amp;&amp;</span></span>
<span id="cb7-29"><a href="#cb7-29"></a><span class="va">+            (forward_range&lt;R2&gt; || sized_range&lt;R2&gt;) &amp;&amp;</span></span>
<span id="cb7-30"><a href="#cb7-30"></a><span class="va">+            indirectly_comparable&lt;iterator_t&lt;R1&gt;, iterator_t&lt;R2&gt;, Pred, Proj1, Proj2&gt;</span></span>
<span id="cb7-31"><a href="#cb7-31"></a><span class="va">+ constexpr bool ranges::ends_with(R1&amp;&amp; r1, R2&amp;&amp; r2, Pred pred = {},</span></span>
<span id="cb7-32"><a href="#cb7-32"></a><span class="va">+                                  Proj1 proj1 = {}, Proj2 proj2 = {});</span></span>
<span id="cb7-33"><a href="#cb7-33"></a></span>
<span id="cb7-34"><a href="#cb7-34"></a>// [alg.modifying.operations], mutating sequence operations</span>
<span id="cb7-35"><a href="#cb7-35"></a>// [alg.copy], copy</span>
<span id="cb7-36"><a href="#cb7-36"></a>...</span></code></pre></div>
</div>
<p>Add the following two sections to <span>25.6
 <a href="https://wg21.link/alg.nonmodifying">[alg.nonmodifying]</a></span>:</p>
<h2 data-number="5.1" id="starts-with-alg.starts.with"><span class="header-section-number">5.1</span> 25.6.14 Starts with [alg.starts.with]<a href="#starts-with-alg.starts.with" class="self-link"></a></h2>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1"></a><span class="kw">template</span><span class="op">&lt;</span>input_iterator I1, sentinel_for<span class="op">&lt;</span>I1<span class="op">&gt;</span> S1, input_iterator I2, sentinel_for<span class="op">&lt;</span>I2<span class="op">&gt;</span> S2,</span>
<span id="cb8-2"><a href="#cb8-2"></a>         <span class="kw">class</span> Pred <span class="op">=</span> ranges<span class="op">::</span>equal_to, <span class="kw">class</span> Proj1 <span class="op">=</span> identity, <span class="kw">class</span> Proj2 <span class="op">=</span> identity<span class="op">&gt;</span></span>
<span id="cb8-3"><a href="#cb8-3"></a>  <span class="kw">requires</span> indirectly_comparable<span class="op">&lt;</span>I1, I2, Pred, Proj1, Proj2<span class="op">&gt;</span></span>
<span id="cb8-4"><a href="#cb8-4"></a><span class="kw">constexpr</span> <span class="dt">bool</span> ranges<span class="op">::</span>starts_with<span class="op">(</span>I1 first1, S1 last1, I2 first2, S2 last2, Pred pred <span class="op">=</span> <span class="op">{}</span>,</span>
<span id="cb8-5"><a href="#cb8-5"></a>                                   Proj1 proj1 <span class="op">=</span> <span class="op">{}</span>, Proj2 proj2 <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb8-6"><a href="#cb8-6"></a><span class="kw">template</span><span class="op">&lt;</span>input_range R1, input_range R2, <span class="kw">class</span> Pred <span class="op">=</span> ranges<span class="op">::</span>equal_to, <span class="kw">class</span> Proj1 <span class="op">=</span> identity,</span>
<span id="cb8-7"><a href="#cb8-7"></a>         <span class="kw">class</span> Proj2 <span class="op">=</span> identity<span class="op">&gt;</span></span>
<span id="cb8-8"><a href="#cb8-8"></a>  <span class="kw">requires</span> indirectly_comparable<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span>R1<span class="op">&gt;</span>, iterator_t<span class="op">&lt;</span>R2<span class="op">&gt;</span>, Pred, Proj1, Proj2<span class="op">&gt;</span></span>
<span id="cb8-9"><a href="#cb8-9"></a><span class="kw">constexpr</span> <span class="dt">bool</span> ranges<span class="op">::</span>starts_with<span class="op">(</span>R1<span class="op">&amp;&amp;</span> r1, R2<span class="op">&amp;&amp;</span> r2, Pred pred <span class="op">=</span> <span class="op">{}</span>,</span>
<span id="cb8-10"><a href="#cb8-10"></a>                                   Proj1 proj1 <span class="op">=</span> <span class="op">{}</span>, Proj2 proj2 <span class="op">=</span> <span class="op">{})</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span> <em>Returns</em>: <code class="sourceCode default">ranges::mismatch(first1, last1, first2, last2, pred, proj1, proj2).in2 == last2</code></p>
<h2 data-number="5.2" id="ends-with-alg.ends.with"><span class="header-section-number">5.2</span> 25.6.15 Ends with [alg.ends.with]<a href="#ends-with-alg.ends.with" class="self-link"></a></h2>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1"></a><span class="kw">template</span><span class="op">&lt;</span>input_iterator I1, sentinel_for<span class="op">&lt;</span>I1<span class="op">&gt;</span> S1, input_iterator I2, sentinel_for<span class="op">&lt;</span>I2<span class="op">&gt;</span> S2,</span>
<span id="cb9-2"><a href="#cb9-2"></a>         <span class="kw">class</span> Pred <span class="op">=</span> ranges<span class="op">::</span>equal_to, <span class="kw">class</span> Proj1 <span class="op">=</span> identity, <span class="kw">class</span> Proj2 <span class="op">=</span> identity<span class="op">&gt;</span></span>
<span id="cb9-3"><a href="#cb9-3"></a>  <span class="kw">requires</span> <span class="op">(</span>forward_iterator<span class="op">&lt;</span>I1<span class="op">&gt;</span> <span class="op">||</span> sized_sentinel_for<span class="op">&lt;</span>S1, I1<span class="op">&gt;)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb9-4"><a href="#cb9-4"></a>           <span class="op">(</span>forward_iterator<span class="op">&lt;</span>I2<span class="op">&gt;</span> <span class="op">||</span> sized_sentinel_for<span class="op">&lt;</span>S2, I2<span class="op">&gt;)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb9-5"><a href="#cb9-5"></a>           indirectly_comparable<span class="op">&lt;</span>I1, I2, Pred, Proj1, Proj2<span class="op">&gt;</span></span>
<span id="cb9-6"><a href="#cb9-6"></a><span class="kw">constexpr</span> <span class="dt">bool</span> ranges<span class="op">::</span>ends_with<span class="op">(</span>I1 first1, S1 last1, I2 first2, S2 last2, Pred pred <span class="op">=</span> <span class="op">{}</span>,</span>
<span id="cb9-7"><a href="#cb9-7"></a>                                 Proj1 proj1 <span class="op">=</span> <span class="op">{}</span>, Proj2 proj2 <span class="op">=</span> <span class="op">{})</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span> Let <code class="sourceCode default">N1</code> be <code class="sourceCode default">last1 - first1</code> and <code class="sourceCode default">N2</code> be <code class="sourceCode default">last2 - first2</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span> <em>Returns</em>: <code class="sourceCode default">false</code> if <code class="sourceCode default">N1 &lt; N2</code>, otherwise <code class="sourceCode default">ranges::equal(first1 + (N1 - N2), last1, first2, last2, pred, proj1, proj2)</code>.</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1"></a><span class="kw">template</span><span class="op">&lt;</span>input_range R1, input_range R2, <span class="kw">class</span> Pred <span class="op">=</span> ranges<span class="op">::</span>equal_to, <span class="kw">class</span> Proj1 <span class="op">=</span> identity,</span>
<span id="cb10-2"><a href="#cb10-2"></a>         <span class="kw">class</span> Proj2 <span class="op">=</span> identity<span class="op">&gt;</span></span>
<span id="cb10-3"><a href="#cb10-3"></a>  <span class="kw">requires</span> <span class="op">(</span>forward_range<span class="op">&lt;</span>R1<span class="op">&gt;</span> <span class="op">||</span> sized_range<span class="op">&lt;</span>R1<span class="op">&gt;)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb10-4"><a href="#cb10-4"></a>           <span class="op">(</span>forward_range<span class="op">&lt;</span>R2<span class="op">&gt;</span> <span class="op">||</span> sized_range<span class="op">&lt;</span>R2<span class="op">&gt;)</span> <span class="op">&amp;&amp;</span></span>
<span id="cb10-5"><a href="#cb10-5"></a>           indirectly_comparable<span class="op">&lt;</span>iterator_t<span class="op">&lt;</span>R1<span class="op">&gt;</span>, iterator_t<span class="op">&lt;</span>R2<span class="op">&gt;</span>, Pred, Proj1, Proj2<span class="op">&gt;</span></span>
<span id="cb10-6"><a href="#cb10-6"></a><span class="kw">constexpr</span> <span class="dt">bool</span> ranges<span class="op">::</span>ends_with<span class="op">(</span>R1<span class="op">&amp;&amp;</span> r1, R2<span class="op">&amp;&amp;</span> r2, Pred pred <span class="op">=</span> <span class="op">{}</span>,</span>
<span id="cb10-7"><a href="#cb10-7"></a>                                 Proj1 proj1 <span class="op">=</span> <span class="op">{}</span>, Proj2 proj2 <span class="op">=</span> <span class="op">{})</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span> Let <code class="sourceCode default">N1</code> be <code class="sourceCode default">ranges::distance(r1)</code> and <code class="sourceCode default">N2</code> be <code class="sourceCode default">ranges::distance(r2)</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span> <em>Returns</em>: <code class="sourceCode default">false</code> if <code class="sourceCode default">N1 &lt; N2</code>, otherwise <code class="sourceCode default">ranges::equal(ranges::drop_view(r1, N1 - N2), r2, pred, proj1, proj2)</code>.</p>
<h1 data-number="6" id="reference-implementation"><span class="header-section-number">6</span> Reference implementation<a href="#reference-implementation" class="self-link"></a></h1>
<p>Both <span class="citation" data-cites="starts_with">[<a href="#ref-starts_with" role="doc-biblioref">starts_with</a>]</span> and <span class="citation" data-cites="ends_with">[<a href="#ref-ends_with" role="doc-biblioref">ends_with</a>]</span> have been implemented in range-v3.</p>
<h1 data-number="7" id="acknowledgements"><span class="header-section-number">7</span> Acknowledgements<a href="#acknowledgements" class="self-link"></a></h1>
<p>The author would like to thank Arien Judge for reviewing the proposal, Johel Ernesto Guerrero Peña for providing an implementation for <code class="sourceCode default">ends_with</code>, and Eric Niebler for merging the respective pull requests to range-v3.</p>
<h1 data-number="8" id="bibliography"><span class="header-section-number">8</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-ends_with">
<p>[ends_with] Johel Ernesto Guerrero Peña and Eric Niebler. ranges::ends_with. <br />
<a href="https://git.io/fjzq0">https://git.io/fjzq0</a></p>
</div>
<div id="ref-N3609">
<p>[N3609] Jeffrey Yasskin. 2013-03-15. string_view: a non-owning reference to a string, revision 3. <br />
<a href="https://wg21.link/n3609">https://wg21.link/n3609</a></p>
</div>
<div id="ref-P0457R2">
<p>[P0457R2] Mikhail Maltsev. 2017-11-11. String Prefix and Suffix Checking. <br />
<a href="https://wg21.link/p0457r2">https://wg21.link/p0457r2</a></p>
</div>
<div id="ref-starts_with">
<p>[starts_with] Christopher Di Bella and Eric Niebler. ranges::starts_with. <br />
<a href="https://git.io/fjzqR">https://git.io/fjzqR</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
