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

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

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

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

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

div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre { 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/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
  
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center"><code class="sourceCode cpp">ranges<span class="op">::</span>fold</code></h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2322R2</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2021-04-14</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      LEWG<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="#revision-history"><span class="toc-section-number">1</span> Revision History<span></span></a></li>
<li><a href="#introduction"><span class="toc-section-number">2</span> Introduction<span></span></a></li>
<li><a href="#return-type"><span class="toc-section-number">3</span> Return Type<span></span></a>
<ul>
<li><a href="#always-return-t"><span class="toc-section-number">3.1</span> Always return <code class="sourceCode cpp">T</code><span></span></a></li>
<li><a href="#return-the-result-of-the-initial-invocation"><span class="toc-section-number">3.2</span> Return the result of the initial invocation<span></span></a></li>
</ul></li>
<li><a href="#other-fold-algorithms"><span class="toc-section-number">4</span> Other <code class="sourceCode cpp">fold</code> algorithms<span></span></a>
<ul>
<li><a href="#fold_first"><span class="toc-section-number">4.1</span> <code class="sourceCode cpp">fold_first</code><span></span></a></li>
<li><a href="#fold_right"><span class="toc-section-number">4.2</span> <code class="sourceCode cpp">fold_right</code><span></span></a></li>
<li><a href="#naming"><span class="toc-section-number">4.3</span> Naming<span></span></a></li>
</ul></li>
<li><a href="#wording"><span class="toc-section-number">5</span> Wording<span></span></a></li>
<li><a href="#bibliography"><span class="toc-section-number">6</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="revision-history"><span class="header-section-number">1</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<p><span class="citation" data-cites="P2322R1">[<a href="#ref-P2322R1" role="doc-biblioref">P2322R1</a>]</span> used <em><code class="sourceCode cpp">weakly<span class="op">-</span>assignable<span class="op">-</span>from</code></em> as the constraint, this elevates it to <code class="sourceCode cpp">assignable_from</code>. This revision also changes the return type of <code class="sourceCode cpp">fold</code> to no longer be the type of the initial value, see <a href="#return-type">the discussion</a>.</p>
<p><span class="citation" data-cites="P2322R0">[<a href="#ref-P2322R0" role="doc-biblioref">P2322R0</a>]</span> used <code class="sourceCode cpp">regular_invocable</code> as the constraint in the <code class="sourceCode cpp"><em>foldable</em></code> concept, but we don’t need that for this algorithm and it prohibits reasonable uses like a mutating operation. <code class="sourceCode cpp">invocable</code> is the sufficient constraint here (in the same way that it is for <code class="sourceCode cpp">for_each</code>). Also restructured the API to overload on providing the initial value instead of having differently named algorithms.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="introduction"><span class="header-section-number">2</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>As described in <span class="citation" data-cites="P2214R0">[<a href="#ref-P2214R0" role="doc-biblioref">P2214R0</a>]</span>, there is one very important rangified algorithm missing from the standard library: <code class="sourceCode cpp">fold</code>.</p>
<p>While we do have an iterator-based version of <code class="sourceCode cpp">fold</code> in the standard library, it is currently named <code class="sourceCode cpp">accumulate</code>, defaults to performing <code class="sourceCode cpp"><span class="op">+</span></code> on its operands, and is found in the header <code class="sourceCode cpp"><span class="op">&lt;</span>numeric<span class="op">&gt;</span></code>. But <code class="sourceCode cpp">fold</code> is much more than addition, so as described in the linked paper, it’s important to give it the more generic name and to avoid a default operator.</p>
<p>Also as described in the linked paper, it is important to avoid over-constraining <code class="sourceCode cpp">fold</code> in a way that prevents using it for heterogeneous folds. As such, the <code class="sourceCode cpp">fold</code> specified in this paper only requires one particular invocation of the binary operator and there is no <code class="sourceCode cpp">common_reference</code> requirement between any of the types involved.</p>
<p>Lastly, the <code class="sourceCode cpp">fold</code> here is proposed to go into <code class="sourceCode cpp"><span class="op">&lt;</span>algorithm<span class="op">&gt;</span></code> rather than <code class="sourceCode cpp"><span class="op">&lt;</span>numeric<span class="op">&gt;</span></code> since there is nothing especially numeric about it.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="return-type"><span class="header-section-number">3</span> Return Type<a href="#return-type" class="self-link"></a></h1>
<p>Consider the example:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">double</span><span class="op">&gt;</span> v <span class="op">=</span> <span class="op">{</span><span class="fl">0.25</span>, <span class="fl">0.75</span><span class="op">}</span>;</span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw">auto</span> r <span class="op">=</span> ranges<span class="op">::</span>fold<span class="op">(</span>v, <span class="dv">1</span>, std<span class="op">::</span>plus<span class="op">())</span>;</span></code></pre></div>
<p>What is the type and value of <code class="sourceCode cpp">r</code>? There are two choices, which I’ll demonstrate with implementations (with incomplete constraints).</p>
<h2 data-number="3.1" id="always-return-t"><span class="header-section-number">3.1</span> Always return <code class="sourceCode cpp">T</code><a href="#always-return-t" class="self-link"></a></h2>
<p>We implement like so:</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>range R, movable T, <span class="kw">typename</span> F<span class="op">&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="kw">auto</span> fold<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, T init, F op<span class="op">)</span> <span class="op">-&gt;</span> T</span>
<span id="cb2-3"><a href="#cb2-3"></a><span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4"></a>    ranges<span class="op">::</span>iterator_t<span class="op">&lt;</span>R<span class="op">&gt;</span> first <span class="op">=</span> ranges<span class="op">::</span>begin<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb2-5"><a href="#cb2-5"></a>    ranges<span class="op">::</span>sentinel_t<span class="op">&lt;</span>R<span class="op">&gt;</span> last <span class="op">=</span> ranges<span class="op">::</span>end<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb2-6"><a href="#cb2-6"></a>    <span class="cf">for</span> <span class="op">(</span>; first <span class="op">!=</span> last; <span class="op">++</span>first<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-7"><a href="#cb2-7"></a>        init <span class="op">=</span> invoke<span class="op">(</span>op, move<span class="op">(</span>init<span class="op">)</span>, <span class="op">*</span>first<span class="op">)</span>;</span>
<span id="cb2-8"><a href="#cb2-8"></a>    <span class="op">}</span></span>
<span id="cb2-9"><a href="#cb2-9"></a>    <span class="cf">return</span> init;</span>
<span id="cb2-10"><a href="#cb2-10"></a><span class="op">}</span></span></code></pre></div>
<p>Here, <code class="sourceCode cpp">fold<span class="op">(</span>v, <span class="dv">1</span>, std<span class="op">::</span>plus<span class="op">())</span></code> is an <code class="sourceCode cpp"><span class="dt">int</span></code> because the initial value is <code class="sourceCode cpp"><span class="dv">1</span></code>. Since our accumulator is an <code class="sourceCode cpp"><span class="dt">int</span></code>, the result here is <code class="sourceCode cpp"><span class="dv">1</span></code>. This is a consistent with <code class="sourceCode cpp">std<span class="op">::</span>accumulate</code> and is simple to reason about and specify. But it is also a common gotcha with <code class="sourceCode cpp">std<span class="op">::</span>accumulate</code>.</p>
<p>Note that if we use <code class="sourceCode cpp">assignable_from<span class="op">&lt;</span>T<span class="op">&amp;</span>, invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, T, range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;&gt;</span></code> as the constraint on this algorithm, in this example this becomes <code class="sourceCode cpp">assignable_from<span class="op">&lt;</span><span class="dt">int</span><span class="op">&amp;</span>, <span class="dt">double</span><span class="op">&gt;</span></code>. We would be violating the semantic requirements of <code class="sourceCode cpp">assignable_from</code>, which state <span>18.4.8
 <a href="https://wg21.link/concept.assignable">[concept.assignable]</a></span>/1.5:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">(1.5)</a></span> After evaluating <code class="sourceCode cpp">lhs <span class="op">=</span> rhs</code>:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(1.5.1)</a></span> <code class="sourceCode cpp">lhs</code> is equal to <code class="sourceCode cpp">rcopy</code>, unless <code class="sourceCode cpp">rhs</code> is a non-const xvalue that refers to <code class="sourceCode cpp">lcopy</code>.</li>
</ul>
</blockquote>
<p>This only holds if all the <code class="sourceCode cpp"><span class="dt">double</span></code>s happen to be whole numbers, which is not the case for our example. This invocation would be violating the semantic constraints of the algorithm.</p>
<h2 data-number="3.2" id="return-the-result-of-the-initial-invocation"><span class="header-section-number">3.2</span> Return the result of the initial invocation<a href="#return-the-result-of-the-initial-invocation" class="self-link"></a></h2>
<p>When we talk about the mathematical definition of fold, that’s <code class="sourceCode cpp">f<span class="op">(</span>f<span class="op">(</span>f<span class="op">(</span>f<span class="op">(</span>init, x1<span class="op">)</span>, x2<span class="op">)</span>, <span class="op">...)</span>, xn<span class="op">)</span></code>. If we actually evaluate this expression in this context, that’s <code class="sourceCode cpp"><span class="op">((</span><span class="dv">1</span> <span class="op">+</span> <span class="fl">0.25</span><span class="op">)</span> <span class="op">+</span> <span class="fl">0.75</span><span class="op">)</span></code> which would be <code class="sourceCode cpp"><span class="fl">2.0</span></code>.</p>
<p>We cannot in general get this type correctly. A hypothetical <code class="sourceCode cpp">f</code> could actually change its type every time which we cannot possibly implement, so we can’t exactly mirror the mathematical definition regardless. But let’s just put that case aside as being fairly silly.</p>
<p>We could at least address the gotcha from <code class="sourceCode cpp">std<span class="op">::</span>accumulate</code> by returning the decayed result of invoking the binary operation with <code class="sourceCode cpp">T</code> (the initial value) and the reference type of the range. That is, <code class="sourceCode cpp">U <span class="op">=</span> decay_t<span class="op">&lt;</span>invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, T, ranges<span class="op">::</span>range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;&gt;</span></code>. There are two possible approaches to implementing a fold that returns <code class="sourceCode cpp">U</code> instead of <code class="sourceCode cpp">T</code>:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Two invocation kinds</strong>
</div></th>
<th><div style="text-align:center">
<strong>One invocation kind</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<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">template</span> <span class="op">&lt;</span>range R, movable T, <span class="kw">typename</span> F,</span>
<span id="cb3-2"><a href="#cb3-2"></a>            <span class="kw">typename</span> U <span class="op">=</span> <span class="co">/* ... */</span><span class="op">&gt;</span></span>
<span id="cb3-3"><a href="#cb3-3"></a><span class="kw">auto</span> fold<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, T init, F f<span class="op">)</span> <span class="op">-&gt;</span> U</span>
<span id="cb3-4"><a href="#cb3-4"></a><span class="op">{</span></span>
<span id="cb3-5"><a href="#cb3-5"></a>    ranges<span class="op">::</span>iterator_t<span class="op">&lt;</span>R<span class="op">&gt;</span> first <span class="op">=</span> ranges<span class="op">::</span>begin<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb3-6"><a href="#cb3-6"></a>    ranges<span class="op">::</span>sentinel_t<span class="op">&lt;</span>R<span class="op">&gt;</span> last <span class="op">=</span> ranges<span class="op">::</span>end<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb3-7"><a href="#cb3-7"></a>    </span>
<span id="cb3-8"><a href="#cb3-8"></a>    <span class="cf">if</span> <span class="op">(</span>first <span class="op">==</span> last<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-9"><a href="#cb3-9"></a>        <span class="cf">return</span> move<span class="op">(</span>init<span class="op">)</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>
<span id="cb3-12"><a href="#cb3-12"></a>    U accum <span class="op">=</span> invoke<span class="op">(</span>f, move<span class="op">(</span>init<span class="op">)</span>, <span class="op">*</span>first<span class="op">)</span>;</span>
<span id="cb3-13"><a href="#cb3-13"></a>    <span class="cf">for</span> <span class="op">(++</span>first; first <span class="op">!=</span> last; <span class="op">++</span>first<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-14"><a href="#cb3-14"></a>        accum <span class="op">=</span> invoke<span class="op">(</span>f, move<span class="op">(</span>accum<span class="op">)</span>, <span class="op">*</span>first<span class="op">)</span>;</span>
<span id="cb3-15"><a href="#cb3-15"></a>    <span class="op">}</span></span>
<span id="cb3-16"><a href="#cb3-16"></a>    <span class="cf">return</span> accum;</span>
<span id="cb3-17"><a href="#cb3-17"></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">template</span> <span class="op">&lt;</span>range R, movable T, <span class="kw">typename</span> F,</span>
<span id="cb4-2"><a href="#cb4-2"></a>            <span class="kw">typename</span> U <span class="op">=</span> <span class="co">/* ... */</span><span class="op">&gt;</span></span>
<span id="cb4-3"><a href="#cb4-3"></a><span class="kw">auto</span> fold<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, T init, F f<span class="op">)</span> <span class="op">-&gt;</span> U</span>
<span id="cb4-4"><a href="#cb4-4"></a><span class="op">{</span></span>
<span id="cb4-5"><a href="#cb4-5"></a>    ranges<span class="op">::</span>iterator_t<span class="op">&lt;</span>R<span class="op">&gt;</span> first <span class="op">=</span> ranges<span class="op">::</span>begin<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb4-6"><a href="#cb4-6"></a>    ranges<span class="op">::</span>sentinel_t<span class="op">&lt;</span>R<span class="op">&gt;</span> last <span class="op">=</span> ranges<span class="op">::</span>end<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb4-7"><a href="#cb4-7"></a>    </span>
<span id="cb4-8"><a href="#cb4-8"></a>    U accum <span class="op">=</span> std<span class="op">::</span>move<span class="op">(</span>init<span class="op">)</span>;</span>
<span id="cb4-9"><a href="#cb4-9"></a>    <span class="cf">for</span> <span class="op">(</span>; first <span class="op">!=</span> last; <span class="op">++</span>first<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-10"><a href="#cb4-10"></a>        accum <span class="op">=</span> invoke<span class="op">(</span>f, move<span class="op">(</span>accum<span class="op">)</span>, <span class="op">*</span>first<span class="op">)</span>;</span>
<span id="cb4-11"><a href="#cb4-11"></a>    <span class="op">}</span></span>
<span id="cb4-12"><a href="#cb4-12"></a>    <span class="cf">return</span> accum;</span>
<span id="cb4-13"><a href="#cb4-13"></a><span class="op">}</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>Either way, our set of requirements is:</p>
<ul>
<li><code class="sourceCode cpp">invocable<span class="op">&lt;</span>F<span class="op">&amp;</span>, T, range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;</span></code> (even though the implementation on the right does not actually invoke the function using these arguments, we still need this to determine the type <code class="sourceCode cpp">U</code>)</li>
<li><code class="sourceCode cpp">invocable<span class="op">&lt;</span>F<span class="op">&amp;</span>, U, range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;</span></code></li>
<li><code class="sourceCode cpp">convertible_to<span class="op">&lt;</span>T, U<span class="op">&gt;</span></code></li>
<li><code class="sourceCode cpp">assignable_from<span class="op">&lt;</span>U<span class="op">&amp;</span>, invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, U, range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;&gt;</span></code></li>
</ul>
<p>While the left-hand side also needs <code class="sourceCode cpp">convertible_to<span class="op">&lt;</span>invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, T, range_reference_t<span class="op">&lt;</span>R<span class="op">&gt;&gt;</span>, U<span class="op">&gt;</span></code>.</p>
<p>This is a fairly complicated set of requirements.</p>
<p>But it means that our example, <code class="sourceCode cpp">fold<span class="op">(</span>v, <span class="dv">1</span>, std<span class="op">::</span>plus<span class="op">())</span></code> yields the more likely expected result of <code class="sourceCode cpp"><span class="fl">2.0</span></code>. So this is the version this paper proposes.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="other-fold-algorithms"><span class="header-section-number">4</span> Other <code class="sourceCode cpp">fold</code> algorithms<a href="#other-fold-algorithms" class="self-link"></a></h1>
<p><span class="citation" data-cites="P2214R0">[<a href="#ref-P2214R0" role="doc-biblioref">P2214R0</a>]</span> proposed a single fold algorithm that takes an initial value and a binary operation and performs a <em>left</em> fold over the range. But there are a couple variants that are also quite valuable and that we should adopt as a family.</p>
<h2 data-number="4.1" id="fold_first"><span class="header-section-number">4.1</span> <code class="sourceCode cpp">fold_first</code><a href="#fold_first" class="self-link"></a></h2>
<p>Sometimes, there is no good choice for the initial value of the fold and you want to use the first element of the range. For instance, if I want to find the smallest string in a range, I can already do that as <code class="sourceCode cpp">ranges<span class="op">::</span>min<span class="op">(</span>r<span class="op">)</span></code> but the only way to express this in terms of <code class="sourceCode cpp">fold</code> is to manually pull out the first element, like so:</p>
<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> b <span class="op">=</span> ranges<span class="op">::</span>begin<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb5-2"><a href="#cb5-2"></a><span class="kw">auto</span> e <span class="op">=</span> ranges<span class="op">::</span>end<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb5-3"><a href="#cb5-3"></a>ranges<span class="op">::</span>fold<span class="op">(</span>ranges<span class="op">::</span>next<span class="op">(</span>b<span class="op">)</span>, e, <span class="op">*</span>b, ranges<span class="op">::</span>min<span class="op">)</span>;</span></code></pre></div>
<p>But this is both tedious to write, and subtly wrong for input ranges anyway since if the <code class="sourceCode cpp">next<span class="op">(</span>b<span class="op">)</span></code> is evaluated before <code class="sourceCode cpp"><span class="op">*</span>b</code>, we have a dangling iterator. This comes up enough that this paper proposes a version of <code class="sourceCode cpp">fold</code> that uses the first element in the range as the initial value (and thus has a precondition that the range is not empty).</p>
<p>This algorithm exists in Rust (under the name <code class="sourceCode cpp">fold_first</code> as a nightly-only experimental API and <code class="sourceCode cpp">fold1</code> in the <code class="sourceCode cpp">Itertools</code> crate) and Haskell (under the name <code class="sourceCode cpp">foldl1</code>) and Scala and Kotlin (which call it <code class="sourceCode cpp">reduce</code>, while the version that takes an initial value is called <code class="sourceCode cpp">fold</code>).</p>
<p>The question is: should we give this algorithm a different name (e.g. <code class="sourceCode cpp">fold_first</code>) or provide a distinct overload of <code class="sourceCode cpp">fold</code>? To answer that question, we have to deal with the question of ambiguity. For two arguments, <code class="sourceCode cpp">fold<span class="op">(</span>xs, a<span class="op">)</span></code> can only be interpreted as a <code class="sourceCode cpp">fold</code> with no initial value using <code class="sourceCode cpp">a</code> as the binary operator. For four arguments, <code class="sourceCode cpp">fold<span class="op">(</span>xs, a, b, c<span class="op">)</span></code> can only be interpreted as a <code class="sourceCode cpp">fold</code> with <code class="sourceCode cpp">a</code> as the initial value, <code class="sourceCode cpp">b</code> as the binary operation that is the reduction function, and <code class="sourceCode cpp">c</code> as a unary projection.</p>
<p>What about <code class="sourceCode cpp">fold<span class="op">(</span>xs, a, b<span class="op">)</span></code>? It could be:</p>
<ol type="1">
<li>Using <code class="sourceCode cpp">a</code> as the initial value and <code class="sourceCode cpp">b</code> as a binary reduction of the form <code class="sourceCode cpp"><span class="op">(</span>A, X<span class="op">)</span> <span class="op">-&gt;</span> A</code>.</li>
<li>Using <code class="sourceCode cpp">a</code> as a binary reduction of the form <code class="sourceCode cpp"><span class="op">(</span>X, Y<span class="op">)</span> <span class="op">-&gt;</span> X</code> and <code class="sourceCode cpp">b</code> as a unary projection of the form <code class="sourceCode cpp">X <span class="op">-&gt;</span> Y</code>.</li>
</ol>
<p>Is it possible for these to collide? It would be an uncommon situation, since <code class="sourceCode cpp">b</code> would have to be both a unary and a binary function. But it is definitely <em>possible</em>:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">auto</span> first <span class="op">=</span> <span class="op">[](</span><span class="kw">auto</span> x, <span class="kw">auto</span><span class="op">...</span> <span class="op">){</span> <span class="cf">return</span> x; <span class="op">}</span>;</span>
<span id="cb6-2"><a href="#cb6-2"></a><span class="kw">auto</span> r <span class="op">=</span> fold<span class="op">(</span>xs, first, first<span class="op">)</span>;</span></code></pre></div>
<p>This call is ambiguous! This works with either interpretation. It would either just return <code class="sourceCode cpp">first</code> (the lambda) in the first case or the first element of the range in the second case, which makes it either completely useless or just mostly useless.</p>
<p>There might be a situation that is actually useful in which there is an ambiguity in these cases. But if one arises, it is fairly straightforward to force the correct interpretation by coercing the last argument to be either a binary or unary function:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="pp">#define FWD</span><span class="op">(</span>x<span class="op">)</span><span class="pp"> </span><span class="kw">static_cast</span><span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>x<span class="op">)&amp;&amp;&gt;(</span>x<span class="op">)</span></span>
<span id="cb7-2"><a href="#cb7-2"></a><span class="pp">#define RETURNS</span><span class="op">(</span>e<span class="op">)</span><span class="pp"> </span><span class="op">-&gt;</span><span class="pp"> </span><span class="kw">decltype</span><span class="op">((</span>e<span class="op">))</span><span class="pp"> </span><span class="op">{</span><span class="pp"> </span><span class="cf">return</span><span class="pp"> </span>e;<span class="pp"> </span><span class="op">}</span></span>
<span id="cb7-3"><a href="#cb7-3"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">auto</span> as_unary <span class="op">=</span> <span class="op">[](</span><span class="kw">auto</span> f<span class="op">){</span> <span class="cf">return</span> <span class="op">[=](</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> x<span class="op">)</span> RETURNS<span class="op">(</span>f<span class="op">(</span>FWD<span class="op">(</span>x<span class="op">)))</span>; <span class="op">}</span>;</span>
<span id="cb7-4"><a href="#cb7-4"></a><span class="kw">inline</span> <span class="kw">constexpr</span> <span class="kw">auto</span> as_binary <span class="op">=</span> <span class="op">[](</span><span class="kw">auto</span> f<span class="op">){</span> <span class="cf">return</span> <span class="op">[=](</span><span class="kw">auto</span><span class="op">&amp;&amp;</span> x, <span class="kw">auto</span><span class="op">&amp;&amp;</span> y<span class="op">)</span> RETURNS<span class="op">(</span>f<span class="op">(</span>FWD<span class="op">(</span>x<span class="op">)</span>, FWD<span class="op">(</span>y<span class="op">)))</span>; <span class="op">}</span>;</span>
<span id="cb7-5"><a href="#cb7-5"></a></span>
<span id="cb7-6"><a href="#cb7-6"></a>fold<span class="op">(</span>xs, first, as_binary<span class="op">(</span>first<span class="op">))</span>; <span class="co">// definitely interpretation #1</span></span>
<span id="cb7-7"><a href="#cb7-7"></a>fold<span class="op">(</span>xs, first, as_unary<span class="op">(</span>first<span class="op">))</span>;  <span class="co">// definitely interpretation #2</span></span></code></pre></div>
<p>As such, this paper proposes an overload for <code class="sourceCode cpp">fold</code> that take no initial value (and have a precondition that the range is non-empty) rather than introducing a different name for this case.</p>
<h2 data-number="4.2" id="fold_right"><span class="header-section-number">4.2</span> <code class="sourceCode cpp">fold_right</code><a href="#fold_right" class="self-link"></a></h2>
<p>While <code class="sourceCode cpp">ranges<span class="op">::</span>fold</code> would be a left-fold, there is also occasionally the need for a <em>right</em>-fold. While a <code class="sourceCode cpp">fold_right</code> is much easier to write in code given <code class="sourceCode cpp">fold</code> than <code class="sourceCode cpp">fold_first</code>, since <code class="sourceCode cpp">fold_right<span class="op">(</span>r, init, op<span class="op">)</span></code> is <code class="sourceCode cpp">fold<span class="op">(</span>r <span class="op">|</span> views<span class="op">::</span>reverse, init, flip<span class="op">(</span>op<span class="op">))</span></code>, it’s sufficiently common that it may as well be in the standard library.</p>
<p>As with the previous section, we should also provide overloads of <code class="sourceCode cpp">fold_right</code> that do not take an initial value.</p>
<p>There are three questions that would need to be asked about <code class="sourceCode cpp">fold_right</code>.</p>
<p>First, the order of operations of to the function. Given <code class="sourceCode cpp">fold_right<span class="op">([</span><span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span><span class="op">]</span>, z, f<span class="op">)</span></code>, is the evaluation <code class="sourceCode cpp">f<span class="op">(</span><span class="dv">1</span>, f<span class="op">(</span><span class="dv">2</span>, f<span class="op">(</span><span class="dv">3</span>, z<span class="op">)))</span></code> or is the evaluation <code class="sourceCode cpp">f<span class="op">(</span>f<span class="op">(</span>f<span class="op">(</span>z, <span class="dv">3</span><span class="op">)</span>, <span class="dv">2</span><span class="op">)</span>, <span class="dv">1</span><span class="op">)</span></code>? Note that either way, we’re choosing the <code class="sourceCode cpp"><span class="dv">3</span></code> then <code class="sourceCode cpp"><span class="dv">2</span></code> then <code class="sourceCode cpp"><span class="dv">1</span></code>, both are right folds. It’s a question of if the initial element is the left-hand operand (as it is in the left <code class="sourceCode cpp">fold</code>) or the right-hand operand (as it would be if consider the right fold as a flip of the left fold). For instance, Scheme picks the former but Haskell picks the latter.</p>
<p>One advantage of the former is that we can specify <code class="sourceCode cpp">fold_right<span class="op">(</span>r, z, op<span class="op">)</span></code> as precisely <code class="sourceCode cpp">fold_left<span class="op">(</span>views<span class="op">::</span>reverse<span class="op">(</span>r<span class="op">)</span>, z, op<span class="op">)</span></code> and leave it at that. With the latter, we would need need slightly more specification and would want to avoid saying <code class="sourceCode cpp">flip<span class="op">(</span>op<span class="op">)</span></code> since directly invoking the operation with the arguments in the correct order is a little better in the case of ranges of prvalues.</p>
<p>This paper picks the latter (that is <code class="sourceCode cpp">fold_right</code> as the order of arguments flipped from <code class="sourceCode cpp">fold</code>).</p>
<p>Second, supporting bidirectional ranges is straightforward. Supporting forward ranges involves recursion of the size of the range. Supporting input ranges involves recursion and also copying the whole range first. Are either of these worth supporting? The paper simply supports bidirectional ranges.</p>
<p>Third, the naming question.</p>
<h2 data-number="4.3" id="naming"><span class="header-section-number">4.3</span> Naming<a href="#naming" class="self-link"></a></h2>
<p>There are roughly three different choices that we could make here:</p>
<ol type="1">
<li>Provide the algorithms <code class="sourceCode cpp">fold</code> (a left-fold) and <code class="sourceCode cpp">fold_right</code>.</li>
<li>Provide the algorithms <code class="sourceCode cpp">fold_left</code> and <code class="sourceCode cpp">fold_right</code>.</li>
<li>Provide the algorithms <code class="sourceCode cpp">fold_left</code> and <code class="sourceCode cpp">fold_right</code> and also provide an alias <code class="sourceCode cpp">fold</code> which is also <code class="sourceCode cpp">fold_left</code>.</li>
</ol>
<p>There’s language precedents for any of these cases. F# and Kotlin both provide <code class="sourceCode cpp">fold</code> as a left-fold and suffixed right-fold (<code class="sourceCode cpp">foldBack</code> in F#, <code class="sourceCode cpp">foldRight</code> in Kotlin). Elm, Haskell, and OCaml provide symmetrically named algorithms (<code class="sourceCode cpp">foldl</code>/<code class="sourceCode cpp">foldr</code> for the first two and <code class="sourceCode cpp">fold_left</code>/<code class="sourceCode cpp">fold_right</code> for the third). Scala provides a <code class="sourceCode cpp">foldLeft</code> and <code class="sourceCode cpp">foldRight</code> while also providing <code class="sourceCode cpp">fold</code> to also mean <code class="sourceCode cpp">foldLeft</code>.</p>
<p>In C++, we don’t have precedent in the library at this point for providing an alias for an algorithm, although we do have precedent in the library for providing an alias for a range adapter (<code class="sourceCode cpp">keys</code> and <code class="sourceCode cpp">values</code> for <code class="sourceCode cpp">elements<span class="op">&lt;</span><span class="dv">0</span><span class="op">&gt;</span></code> and <code class="sourceCode cpp">elements<span class="op">&lt;</span><span class="dv">1</span><span class="op">&gt;</span></code>, and <span class="citation" data-cites="P2321R0">[<a href="#ref-P2321R0" role="doc-biblioref">P2321R0</a>]</span> proposes <code class="sourceCode cpp">pairwise</code> and <code class="sourceCode cpp">pairwise_transform</code> as aliases for <code class="sourceCode cpp">adjacent<span class="op">&lt;</span><span class="dv">2</span><span class="op">&gt;</span></code> and <code class="sourceCode cpp">adjacent_transform<span class="op">&lt;</span><span class="dv">2</span><span class="op">&gt;</span></code>). We also have precedent in the library for asymmetric names (<code class="sourceCode cpp">sort</code> vs <code class="sourceCode cpp">stable_sort</code> vs <code class="sourceCode cpp">partial_sort</code>), although those algorithms are not as symmetric as <code class="sourceCode cpp">fold_left</code> and <code class="sourceCode cpp">fold_right</code>… while we do also have <code class="sourceCode cpp">shift_left</code> and <code class="sourceCode cpp">shift_right</code>.</p>
<p>All of which is to say, I don’t think there’s a clear answer to this question. I would be quite happy with any of the three options. This paper picks (2).</p>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="wording"><span class="header-section-number">5</span> Wording<a href="#wording" class="self-link"></a></h1>
<p>Append to <span>25.4
 <a href="https://wg21.link/algorithm.syn">[algorithm.syn]</a></span>:</p>
<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1"></a><span class="pp">#include </span><span class="im">&lt;initializer_list&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2"></a></span>
<span id="cb8-3"><a href="#cb8-3"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb8-4"><a href="#cb8-4"></a>  <span class="co">// ...</span></span>
<span id="cb8-5"><a href="#cb8-5"></a>    </span>
<span id="cb8-6"><a href="#cb8-6"></a>  <span class="co">// [alg.fold], folds</span></span>
<span id="cb8-7"><a href="#cb8-7"></a>  <span class="kw">namespace</span> ranges <span class="op">{</span></span>
<span id="cb8-8"><a href="#cb8-8"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> F<span class="op">&gt;</span></span>
<span id="cb8-9"><a href="#cb8-9"></a>    <span class="kw">struct</span> <em>flipped</em> <span class="op">{</span>  <span class="co">// exposition only</span></span>
<span id="cb8-10"><a href="#cb8-10"></a>      F f;</span>
<span id="cb8-11"><a href="#cb8-11"></a>      </span>
<span id="cb8-12"><a href="#cb8-12"></a>      <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb8-13"><a href="#cb8-13"></a>        <span class="kw">requires</span> invocable<span class="op">&lt;</span>F<span class="op">&amp;</span>, U, T<span class="op">&gt;</span></span>
<span id="cb8-14"><a href="#cb8-14"></a>      <span class="kw">constexpr</span> invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, U, T<span class="op">&gt;</span> <span class="kw">operator</span><span class="op">()(</span>T<span class="op">&amp;&amp;</span>, U<span class="op">&amp;&amp;)</span>;</span>
<span id="cb8-15"><a href="#cb8-15"></a>    <span class="op">}</span>;</span>
<span id="cb8-16"><a href="#cb8-16"></a>    </span>
<span id="cb8-17"><a href="#cb8-17"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> F, <span class="kw">class</span> T, <span class="kw">class</span> I, <span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb8-18"><a href="#cb8-18"></a>    <span class="kw">concept</span> <em>indirectly-binary-left-foldable-impl</em> <span class="op">=</span>  <span class="co">// exposition only</span></span>
<span id="cb8-19"><a href="#cb8-19"></a>        movable<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb8-20"><a href="#cb8-20"></a>        movable<span class="op">&lt;</span>U<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb8-21"><a href="#cb8-21"></a>        convertible_to<span class="op">&lt;</span>T, U<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb8-22"><a href="#cb8-22"></a>        invocable<span class="op">&lt;</span>F<span class="op">&amp;</span>, U, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb8-23"><a href="#cb8-23"></a>        assignable_from<span class="op">&lt;</span>U<span class="op">&amp;</span>, invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, U, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;&gt;</span>;    </span>
<span id="cb8-24"><a href="#cb8-24"></a>    </span>
<span id="cb8-25"><a href="#cb8-25"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> F, <span class="kw">class</span> T, <span class="kw">class</span> I<span class="op">&gt;</span></span>
<span id="cb8-26"><a href="#cb8-26"></a>    <span class="kw">concept</span> <em>indirectly-binary-left-foldable</em> <span class="op">=</span>      <span class="co">// exposition only</span></span>
<span id="cb8-27"><a href="#cb8-27"></a>        copy_constructible<span class="op">&lt;</span>F<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb8-28"><a href="#cb8-28"></a>        indirectly_readable<span class="op">&lt;</span>I<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb8-29"><a href="#cb8-29"></a>        invocable<span class="op">&lt;</span>F<span class="op">&amp;</span>, T, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb8-30"><a href="#cb8-30"></a>        convertible_to<span class="op">&lt;</span>invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, T, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span>,</span>
<span id="cb8-31"><a href="#cb8-31"></a>               decay_t<span class="op">&lt;</span>invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, T, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;&gt;&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb8-32"><a href="#cb8-32"></a>        <em>indirectly-binary-left-foldable-impl</em><span class="op">&lt;</span>F, T, I, decay_t<span class="op">&lt;</span>invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, T, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;&gt;&gt;</span>; </span>
<span id="cb8-33"><a href="#cb8-33"></a></span>
<span id="cb8-34"><a href="#cb8-34"></a>    <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> F, <span class="kw">class</span> T, <span class="kw">class</span> I<span class="op">&gt;</span></span>
<span id="cb8-35"><a href="#cb8-35"></a>    <span class="kw">concept</span> <em>indirectly-binary-right-foldable</em> <span class="op">=</span>    <span class="co">// exposition only</span></span>
<span id="cb8-36"><a href="#cb8-36"></a>        <em>indirectly-binary-left-foldable</em><span class="op">&lt;</span><em>flipped</em><span class="op">&lt;</span>F<span class="op">&gt;</span>, T, I<span class="op">&gt;</span>;    </span>
<span id="cb8-37"><a href="#cb8-37"></a>  </span>
<span id="cb8-38"><a href="#cb8-38"></a>    <span class="kw">template</span><span class="op">&lt;</span>input_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, <span class="kw">class</span> T, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb8-39"><a href="#cb8-39"></a>      <em>indirectly-binary-left-foldable</em><span class="op">&lt;</span>T, projected<span class="op">&lt;</span>I, Proj<span class="op">&gt;&gt;</span> F<span class="op">&gt;</span></span>
<span id="cb8-40"><a href="#cb8-40"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> fold_left<span class="op">(</span>I first, S last, T init, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb8-41"><a href="#cb8-41"></a></span>
<span id="cb8-42"><a href="#cb8-42"></a>    <span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">class</span> T, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb8-43"><a href="#cb8-43"></a>      <em>indirectly-binary-left-foldable</em><span class="op">&lt;</span>T, 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> F<span class="op">&gt;</span></span>
<span id="cb8-44"><a href="#cb8-44"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> fold_left<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, T init, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb8-45"><a href="#cb8-45"></a></span>
<span id="cb8-46"><a href="#cb8-46"></a>    <span class="kw">template</span> <span class="op">&lt;</span>input_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb8-47"><a href="#cb8-47"></a>      <em>indirectly-binary-left-foldable</em><span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, projected<span class="op">&lt;</span>I, Proj<span class="op">&gt;&gt;</span> F<span class="op">&gt;</span></span>
<span id="cb8-48"><a href="#cb8-48"></a>      <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span></span>
<span id="cb8-49"><a href="#cb8-49"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> fold_left<span class="op">(</span>I first, S last, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb8-50"><a href="#cb8-50"></a></span>
<span id="cb8-51"><a href="#cb8-51"></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="cb8-52"><a href="#cb8-52"></a>      <em>indirectly-binary-left-foldable</em><span class="op">&lt;</span>range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</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> F<span class="op">&gt;</span></span>
<span id="cb8-53"><a href="#cb8-53"></a>      <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>range_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, range_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span></span>
<span id="cb8-54"><a href="#cb8-54"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> fold_left<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb8-55"><a href="#cb8-55"></a>    </span>
<span id="cb8-56"><a href="#cb8-56"></a>    <span class="kw">template</span><span class="op">&lt;</span>bidirectional_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, <span class="kw">class</span> T, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb8-57"><a href="#cb8-57"></a>      <em>indirectly-binary-right-foldable</em><span class="op">&lt;</span>T, projected<span class="op">&lt;</span>I, Proj<span class="op">&gt;&gt;</span> F<span class="op">&gt;</span></span>
<span id="cb8-58"><a href="#cb8-58"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> fold_right<span class="op">(</span>I first, S last, T init, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb8-59"><a href="#cb8-59"></a></span>
<span id="cb8-60"><a href="#cb8-60"></a>    <span class="kw">template</span><span class="op">&lt;</span>bidirectional_range R, <span class="kw">class</span> T, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb8-61"><a href="#cb8-61"></a>      <em>indirectly-binary-right-foldable</em><span class="op">&lt;</span>T, 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> F<span class="op">&gt;</span></span>
<span id="cb8-62"><a href="#cb8-62"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> fold_right<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, T init, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb8-63"><a href="#cb8-63"></a></span>
<span id="cb8-64"><a href="#cb8-64"></a>    <span class="kw">template</span> <span class="op">&lt;</span>bidirectional_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb8-65"><a href="#cb8-65"></a>      <em>indirectly-binary-right-foldable</em><span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, projected<span class="op">&lt;</span>I, Proj<span class="op">&gt;&gt;</span> F<span class="op">&gt;</span></span>
<span id="cb8-66"><a href="#cb8-66"></a>      <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span></span>
<span id="cb8-67"><a href="#cb8-67"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> fold_right<span class="op">(</span>I first, S last, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb8-68"><a href="#cb8-68"></a></span>
<span id="cb8-69"><a href="#cb8-69"></a>    <span class="kw">template</span> <span class="op">&lt;</span>bidirectional_range R, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb8-70"><a href="#cb8-70"></a>      <em>indirectly-binary-right-foldable</em><span class="op">&lt;</span>range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</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> F<span class="op">&gt;</span></span>
<span id="cb8-71"><a href="#cb8-71"></a>      <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>range_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, range_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span></span>
<span id="cb8-72"><a href="#cb8-72"></a>    <span class="kw">constexpr</span> <span class="kw">auto</span> fold_right<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;    </span>
<span id="cb8-73"><a href="#cb8-73"></a>  <span class="op">}</span></span>
<span id="cb8-74"><a href="#cb8-74"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>And add a new clause, [alg.fold]:</p>
<blockquote>
<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 I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, <span class="kw">class</span> T, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb9-2"><a href="#cb9-2"></a>  <em>indirectly-binary-left-foldable</em><span class="op">&lt;</span>T, projected<span class="op">&lt;</span>I, Proj<span class="op">&gt;&gt;</span> F<span class="op">&gt;</span></span>
<span id="cb9-3"><a href="#cb9-3"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ranges<span class="op">::</span>fold_left<span class="op">(</span>I first, S last, T init, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb9-4"><a href="#cb9-4"></a></span>
<span id="cb9-5"><a href="#cb9-5"></a><span class="kw">template</span><span class="op">&lt;</span>input_range R, <span class="kw">class</span> T, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb9-6"><a href="#cb9-6"></a>  <em>indirectly-binary-left-foldable</em><span class="op">&lt;</span>T, 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> F<span class="op">&gt;</span></span>
<span id="cb9-7"><a href="#cb9-7"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ranges<span class="op">::</span>fold_left<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, T init, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span> <em>Effects</em>: Equivalent to:</p>
<blockquote>
<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">using</span> U <span class="op">=</span> invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, T, indirect_result_t<span class="op">&lt;</span>Proj<span class="op">&amp;</span>, I<span class="op">&gt;&gt;</span>;</span>
<span id="cb10-2"><a href="#cb10-2"></a><span class="cf">if</span> <span class="op">(</span>first <span class="op">==</span> last<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3"></a>    <span class="cf">return</span> U<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>init<span class="op">))</span>;</span>
<span id="cb10-4"><a href="#cb10-4"></a><span class="op">}</span></span>
<span id="cb10-5"><a href="#cb10-5"></a></span>
<span id="cb10-6"><a href="#cb10-6"></a>U accum <span class="op">=</span> invoke<span class="op">(</span>f, std<span class="op">::</span>move<span class="op">(</span>init<span class="op">)</span>, invoke<span class="op">(</span>proj, <span class="op">*</span>first<span class="op">))</span>;</span>
<span id="cb10-7"><a href="#cb10-7"></a><span class="cf">for</span> <span class="op">(++</span>first; first <span class="op">!=</span> last; <span class="op">++</span>first<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-8"><a href="#cb10-8"></a>    accum <span class="op">=</span> invoke<span class="op">(</span>f, std<span class="op">::</span>move<span class="op">(</span>accum<span class="op">)</span>, invoke<span class="op">(</span>proj, <span class="op">*</span>first<span class="op">))</span>;</span>
<span id="cb10-9"><a href="#cb10-9"></a><span class="op">}</span></span>
<span id="cb10-10"><a href="#cb10-10"></a><span class="cf">return</span> accum;</span></code></pre></div>
</blockquote>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1"></a><span class="kw">template</span> <span class="op">&lt;</span>input_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb11-2"><a href="#cb11-2"></a>  <em>indirectly-binary-left-foldable</em><span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, projected<span class="op">&lt;</span>I, Proj<span class="op">&gt;&gt;</span> F<span class="op">&gt;</span></span>
<span id="cb11-3"><a href="#cb11-3"></a>  <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span></span>
<span id="cb11-4"><a href="#cb11-4"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ranges<span class="op">::</span>fold_left<span class="op">(</span>I first, S last, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb11-5"><a href="#cb11-5"></a></span>
<span id="cb11-6"><a href="#cb11-6"></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="cb11-7"><a href="#cb11-7"></a>  <em>indirectly-binary-left-foldable</em><span class="op">&lt;</span>range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</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> F<span class="op">&gt;</span></span>
<span id="cb11-8"><a href="#cb11-8"></a>  <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>range_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, range_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span></span>
<span id="cb11-9"><a href="#cb11-9"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ranges<span class="op">::</span>fold_left<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span> <em>Preconditions</em>: <code class="sourceCode cpp">first <span class="op">!=</span> last</code> is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span> <em>Effects</em>: Equivalent to <code class="sourceCode cpp"><span class="cf">return</span> ranges<span class="op">::</span>fold_left<span class="op">(</span>ranges<span class="op">::</span>next<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>first<span class="op">))</span>, std<span class="op">::</span>move<span class="op">(</span>last<span class="op">)</span>, iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;(*</span>first<span class="op">)</span>, f, proj<span class="op">)</span></code> except ensuring that the initial value is constructed before the iterator is incremented if <code class="sourceCode cpp">first</code> is an input iterator.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1"></a><span class="kw">template</span><span class="op">&lt;</span>bidirectional_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, <span class="kw">class</span> T, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb12-2"><a href="#cb12-2"></a>  <em>indirectly-binary-right-foldable</em><span class="op">&lt;</span>T, projected<span class="op">&lt;</span>I, Proj<span class="op">&gt;&gt;</span> F<span class="op">&gt;</span></span>
<span id="cb12-3"><a href="#cb12-3"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ranges<span class="op">::</span>fold_right<span class="op">(</span>I first, S last, T init, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb12-4"><a href="#cb12-4"></a></span>
<span id="cb12-5"><a href="#cb12-5"></a><span class="kw">template</span><span class="op">&lt;</span>bidirectional_range R, <span class="kw">class</span> T, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb12-6"><a href="#cb12-6"></a>  <em>indirectly-binary-right-foldable</em><span class="op">&lt;</span>T, 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> F<span class="op">&gt;</span></span>
<span id="cb12-7"><a href="#cb12-7"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ranges<span class="op">::</span>fold_right<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, T init, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span> <em>Effects</em>: Equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1"></a><span class="kw">using</span> U <span class="op">=</span> invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, indirect_result_t<span class="op">&lt;</span>Proj<span class="op">&amp;</span>, I<span class="op">&gt;</span>, T<span class="op">&gt;</span>;</span>
<span id="cb13-2"><a href="#cb13-2"></a></span>
<span id="cb13-3"><a href="#cb13-3"></a><span class="cf">if</span> <span class="op">(</span>first <span class="op">==</span> last<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4"></a>    <span class="cf">return</span> U<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>init<span class="op">))</span>;</span>
<span id="cb13-5"><a href="#cb13-5"></a><span class="op">}</span></span>
<span id="cb13-6"><a href="#cb13-6"></a></span>
<span id="cb13-7"><a href="#cb13-7"></a>I tail <span class="op">=</span> ranges<span class="op">::</span>next<span class="op">(</span>first, last<span class="op">)</span>;</span>
<span id="cb13-8"><a href="#cb13-8"></a>U accum <span class="op">=</span> invoke<span class="op">(</span>f, invoke<span class="op">(</span>proj, <span class="op">*--</span>tail<span class="op">)</span>, std<span class="op">::</span>move<span class="op">(</span>init<span class="op">))</span>;</span>
<span id="cb13-9"><a href="#cb13-9"></a><span class="cf">while</span> <span class="op">(</span>first <span class="op">!=</span> tail<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-10"><a href="#cb13-10"></a>    accum <span class="op">=</span> invoke<span class="op">(</span>f, invoke<span class="op">(</span>proj, <span class="op">*--</span>tail<span class="op">)</span>, std<span class="op">::</span>move<span class="op">(</span>accum<span class="op">))</span>;</span>
<span id="cb13-11"><a href="#cb13-11"></a><span class="op">}</span></span>
<span id="cb13-12"><a href="#cb13-12"></a><span class="cf">return</span> accum;</span></code></pre></div>
</blockquote>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1"></a><span class="kw">template</span> <span class="op">&lt;</span>bidirectional_iterator I, sentinel_for<span class="op">&lt;</span>I<span class="op">&gt;</span> S, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb14-2"><a href="#cb14-2"></a>  <em>indirectly-binary-right-foldable</em><span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, projected<span class="op">&lt;</span>I, Proj<span class="op">&gt;&gt;</span> F<span class="op">&gt;</span></span>
<span id="cb14-3"><a href="#cb14-3"></a>  <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span></span>
<span id="cb14-4"><a href="#cb14-4"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ranges<span class="op">::</span>fold_right<span class="op">(</span>I first, S last, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb14-5"><a href="#cb14-5"></a></span>
<span id="cb14-6"><a href="#cb14-6"></a><span class="kw">template</span> <span class="op">&lt;</span>bidirectional_range R, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb14-7"><a href="#cb14-7"></a>  <em>indirectly-binary-right-foldable</em><span class="op">&lt;</span>range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</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> F<span class="op">&gt;</span></span>
<span id="cb14-8"><a href="#cb14-8"></a>  <span class="kw">requires</span> constructible_from<span class="op">&lt;</span>range_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, range_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span></span>
<span id="cb14-9"><a href="#cb14-9"></a><span class="kw">constexpr</span> <span class="kw">auto</span> ranges<span class="op">::</span>fold_right<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, F f, Proj proj <span class="op">=</span> <span class="op">{})</span>;  </span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span> <em>Preconditions</em>: <code class="sourceCode cpp">first <span class="op">!=</span> last</code> is <code class="sourceCode cpp"><span class="kw">true</span></code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span> <em>Effects</em>: Equivalent to:</p>
<blockquote>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1"></a>I tail <span class="op">=</span> ranges<span class="op">::</span>prev<span class="op">(</span>ranges<span class="op">::</span>next<span class="op">(</span>first, std<span class="op">::</span>move<span class="op">(</span>last<span class="op">)))</span>;</span>
<span id="cb15-2"><a href="#cb15-2"></a><span class="cf">return</span> ranges<span class="op">::</span>fold_right<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>first<span class="op">)</span>, tail, iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;(*</span>tail<span class="op">)</span>, f, proj<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</blockquote>
<h1 data-number="6" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">6</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-P2214R0">
<p>[P2214R0] Barry Revzin, Conor Hoekstra, Tim Song. 2020-10-15. A Plan for C++23 Ranges. <br />
<a href="https://wg21.link/p2214r0">https://wg21.link/p2214r0</a></p>
</div>
<div id="ref-P2321R0">
<p>[P2321R0] Tim Song. 2021-02-21. zip. <br />
<a href="https://wg21.link/p2321r0">https://wg21.link/p2321r0</a></p>
</div>
<div id="ref-P2322R0">
<p>[P2322R0] Barry Revzin. 2021-02-18. ranges::fold. <br />
<a href="https://wg21.link/p2322r0">https://wg21.link/p2322r0</a></p>
</div>
<div id="ref-P2322R1">
<p>[P2322R1] Barry Revzin. 2021-03-17. ranges::fold. <br />
<a href="https://wg21.link/p2322r1">https://wg21.link/p2322r1</a></p>
</div>
</div>
</div>
</div>
</body>
</html>
