<!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-16" />
  <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>P2322R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2021-02-16</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="#introduction"><span class="toc-section-number">1</span> Introduction<span></span></a></li>
<li><a href="#other-fold-algorithms"><span class="toc-section-number">2</span> Other <code class="sourceCode cpp">fold</code> algorithms<span></span></a>
<ul>
<li><a href="#fold_first"><span class="toc-section-number">2.1</span> <code class="sourceCode cpp">fold_first</code><span></span></a></li>
<li><a href="#fold_right"><span class="toc-section-number">2.2</span> <code class="sourceCode cpp">fold_right</code><span></span></a></li>
</ul></li>
<li><a href="#wording"><span class="toc-section-number">3</span> Wording<span></span></a></li>
<li><a href="#bibliography"><span class="toc-section-number">4</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="introduction"><span class="header-section-number">1</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="2" style="border-bottom:1px solid #cccccc" id="other-fold-algorithms"><span class="header-section-number">2</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="2.1" id="fold_first"><span class="header-section-number">2.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="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-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="cb1-2"><a href="#cb1-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="cb1-3"><a href="#cb1-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>). This paper proposes the name <code class="sourceCode cpp">fold_first</code> rather than deal with the question of if we can sufficiently constrain our overloads to avoid ambiguity. Plus, the fact that <code class="sourceCode cpp">fold</code> has no preconditions but <code class="sourceCode cpp">fold_first</code> does suggests that they should have different names.</p>
<h2 data-number="2.2" id="fold_right"><span class="header-section-number">2.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 <code class="sourceCode cpp">fold_first</code>, we should also provide a <code class="sourceCode cpp">fold_right_last</code>.</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. Given that we have <code class="sourceCode cpp">fold_right</code>, should the other one be named <code class="sourceCode cpp">fold_left</code>? Or we could take Haskell’s names of <code class="sourceCode cpp">foldl</code> and <code class="sourceCode cpp">foldr</code>? In my experience, left-folds are more common than right-folds, so this paper proposes the names <code class="sourceCode cpp">fold</code>/<code class="sourceCode cpp">fold_first</code> and <code class="sourceCode cpp">fold_right</code>/<code class="sourceCode cpp">fold_right_last</code>.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="wording"><span class="header-section-number">3</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="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="pp">#include </span><span class="im">&lt;initializer_list&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2"></a></span>
<span id="cb2-3"><a href="#cb2-3"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4"></a>  <span class="co">// ...</span></span>
<span id="cb2-5"><a href="#cb2-5"></a>    </span>
<span id="cb2-6"><a href="#cb2-6"></a>  <span class="co">// [alg.fold], folds</span></span>
<span id="cb2-7"><a href="#cb2-7"></a>  <span class="kw">namespace</span> ranges <span class="op">{</span></span>
<span id="cb2-8"><a href="#cb2-8"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> LHS, <span class="kw">class</span> RHS<span class="op">&gt;</span></span>
<span id="cb2-9"><a href="#cb2-9"></a>    <span class="kw">concept</span> <em>weakly-assignable-from</em> <span class="op">=</span>          <span class="co">// exposition only</span></span>
<span id="cb2-10"><a href="#cb2-10"></a>      <span class="kw">requires</span><span class="op">(</span>LHS lhs, RHS<span class="op">&amp;&amp;</span> rhs<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-11"><a href="#cb2-11"></a>        <span class="op">{</span> lhs <span class="op">=</span> std<span class="op">::</span>forward<span class="op">&lt;</span>RHS<span class="op">&gt;(</span>rhs<span class="op">)</span>; <span class="op">}</span> <span class="op">-&gt;</span> same_as<span class="op">&lt;</span>LHS<span class="op">&gt;</span>;</span>
<span id="cb2-12"><a href="#cb2-12"></a>      <span class="op">}</span>;</span>
<span id="cb2-13"><a href="#cb2-13"></a>      </span>
<span id="cb2-14"><a href="#cb2-14"></a>    <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> F, <span class="kw">class</span> R, <span class="kw">class</span><span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb2-15"><a href="#cb2-15"></a>    <span class="kw">concept</span> <em>foldable</em> <span class="op">=</span>                        <span class="co">// exposition only</span></span>
<span id="cb2-16"><a href="#cb2-16"></a>      movable<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb2-17"><a href="#cb2-17"></a>      copy_constructible<span class="op">&lt;</span>F<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb2-18"><a href="#cb2-18"></a>      regular_invocable<span class="op">&lt;</span>F<span class="op">&amp;</span>, Args<span class="op">...&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb2-19"><a href="#cb2-19"></a>      <em>weakly-assignable-from</em><span class="op">&lt;</span>R<span class="op">&amp;</span>, invoke_result_t<span class="op">&lt;</span>F<span class="op">&amp;</span>, Args<span class="op">...&gt;&gt;</span>;</span>
<span id="cb2-20"><a href="#cb2-20"></a>  </span>
<span id="cb2-21"><a href="#cb2-21"></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="cb2-22"><a href="#cb2-22"></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="cb2-23"><a href="#cb2-23"></a>      indirectly_readable<span class="op">&lt;</span>I<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb2-24"><a href="#cb2-24"></a>      <em>foldable</em><span class="op">&lt;</span>F, T, T, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;&gt;</span>;</span>
<span id="cb2-25"><a href="#cb2-25"></a>      </span>
<span id="cb2-26"><a href="#cb2-26"></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="cb2-27"><a href="#cb2-27"></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="cb2-28"><a href="#cb2-28"></a>      indirectly_readable<span class="op">&lt;</span>I<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb2-29"><a href="#cb2-29"></a>      <em>foldable</em><span class="op">&lt;</span>F, T, iter_reference_t<span class="op">&lt;</span>I<span class="op">&gt;</span>, T<span class="op">&gt;</span>;      </span>
<span id="cb2-30"><a href="#cb2-30"></a></span>
<span id="cb2-31"><a href="#cb2-31"></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="cb2-32"><a href="#cb2-32"></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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb2-33"><a href="#cb2-33"></a>    <span class="kw">constexpr</span> T fold<span class="op">(</span>I first, S last, T init, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb2-34"><a href="#cb2-34"></a></span>
<span id="cb2-35"><a href="#cb2-35"></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="cb2-36"><a href="#cb2-36"></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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb2-37"><a href="#cb2-37"></a>    <span class="kw">constexpr</span> T fold<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, T init, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb2-38"><a href="#cb2-38"></a></span>
<span id="cb2-39"><a href="#cb2-39"></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="cb2-40"><a href="#cb2-40"></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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb2-41"><a href="#cb2-41"></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="cb2-42"><a href="#cb2-42"></a>    <span class="kw">constexpr</span> iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span> fold_first<span class="op">(</span>I first, S last, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb2-43"><a href="#cb2-43"></a></span>
<span id="cb2-44"><a href="#cb2-44"></a>    <span class="kw">template</span> <span class="op">&lt;</span>input_range R, <span class="kw">class</span> Proj <span class="op">=</span> identity,</span>
<span id="cb2-45"><a href="#cb2-45"></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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb2-46"><a href="#cb2-46"></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="cb2-47"><a href="#cb2-47"></a>    <span class="kw">constexpr</span> range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</span> fold_first<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb2-48"><a href="#cb2-48"></a>    </span>
<span id="cb2-49"><a href="#cb2-49"></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="cb2-50"><a href="#cb2-50"></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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb2-51"><a href="#cb2-51"></a>    <span class="kw">constexpr</span> T fold_right<span class="op">(</span>I first, S last, T init, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb2-52"><a href="#cb2-52"></a></span>
<span id="cb2-53"><a href="#cb2-53"></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="cb2-54"><a href="#cb2-54"></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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb2-55"><a href="#cb2-55"></a>    <span class="kw">constexpr</span> T fold_right<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, T init, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb2-56"><a href="#cb2-56"></a></span>
<span id="cb2-57"><a href="#cb2-57"></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="cb2-58"><a href="#cb2-58"></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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb2-59"><a href="#cb2-59"></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="cb2-60"><a href="#cb2-60"></a>    <span class="kw">constexpr</span> iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span> fold_right_last<span class="op">(</span>I first, S last, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb2-61"><a href="#cb2-61"></a></span>
<span id="cb2-62"><a href="#cb2-62"></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="cb2-63"><a href="#cb2-63"></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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb2-64"><a href="#cb2-64"></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="cb2-65"><a href="#cb2-65"></a>    <span class="kw">constexpr</span> range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</span> fold_right_last<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;    </span>
<span id="cb2-66"><a href="#cb2-66"></a>  <span class="op">}</span></span>
<span id="cb2-67"><a href="#cb2-67"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>And add a new clause, [alg.fold]:</p>
<blockquote>
<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>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="cb3-2"><a href="#cb3-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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb3-3"><a href="#cb3-3"></a><span class="kw">constexpr</span> T ranges<span class="op">::</span>fold<span class="op">(</span>I first, S last, T init, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb3-4"><a href="#cb3-4"></a></span>
<span id="cb3-5"><a href="#cb3-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="cb3-6"><a href="#cb3-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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb3-7"><a href="#cb3-7"></a><span class="kw">constexpr</span> T ranges<span class="op">::</span>fold<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, T init, BinaryOperation binary_op, 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="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="cf">while</span> <span class="op">(</span>first <span class="op">!=</span> last<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2"></a>    init <span class="op">=</span> invoke<span class="op">(</span>binary_op, 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="cb4-3"><a href="#cb4-3"></a>    <span class="op">++</span>first;</span>
<span id="cb4-4"><a href="#cb4-4"></a><span class="op">}</span></span>
<span id="cb4-5"><a href="#cb4-5"></a><span class="cf">return</span> init;</span></code></pre></div>
</blockquote>
<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">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="cb5-2"><a href="#cb5-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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb5-3"><a href="#cb5-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="cb5-4"><a href="#cb5-4"></a><span class="kw">constexpr</span> iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span> ranges<span class="op">::</span>fold_first<span class="op">(</span>I first, S last, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb5-5"><a href="#cb5-5"></a></span>
<span id="cb5-6"><a href="#cb5-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="cb5-7"><a href="#cb5-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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb5-8"><a href="#cb5-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="cb5-9"><a href="#cb5-9"></a><span class="kw">constexpr</span> range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</span> ranges<span class="op">::</span>fold_first<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, BinaryOperation binary_op, 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<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>, binary_op, 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="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-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="cb6-2"><a href="#cb6-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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb6-3"><a href="#cb6-3"></a><span class="kw">constexpr</span> T ranges<span class="op">::</span>fold_right<span class="op">(</span>I first, S last, T init, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb6-4"><a href="#cb6-4"></a></span>
<span id="cb6-5"><a href="#cb6-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="cb6-6"><a href="#cb6-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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb6-7"><a href="#cb6-7"></a><span class="kw">constexpr</span> T ranges<span class="op">::</span>fold_right<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, T init, BinaryOperation binary_op, 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="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></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="cb7-2"><a href="#cb7-2"></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="cb7-3"><a href="#cb7-3"></a>    init <span class="op">=</span> invoke<span class="op">(</span>binary_op, 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="cb7-4"><a href="#cb7-4"></a><span class="op">}</span></span>
<span id="cb7-5"><a href="#cb7-5"></a><span class="cf">return</span> init;</span></code></pre></div>
</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="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-2"><a href="#cb8-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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb8-3"><a href="#cb8-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="cb8-4"><a href="#cb8-4"></a><span class="kw">constexpr</span> iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span> fold_right_last<span class="op">(</span>I first, S last, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb8-5"><a href="#cb8-5"></a></span>
<span id="cb8-6"><a href="#cb8-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="cb8-7"><a href="#cb8-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> BinaryOperation<span class="op">&gt;</span></span>
<span id="cb8-8"><a href="#cb8-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="cb8-9"><a href="#cb8-9"></a><span class="kw">constexpr</span> range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</span> fold_right_last<span class="op">(</span>R<span class="op">&amp;&amp;</span> r, BinaryOperation binary_op, 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="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-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="cb9-2"><a href="#cb9-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>, binary_op, proj<span class="op">)</span>;</span></code></pre></div>
</blockquote>
</blockquote>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">4</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>
</div>
</div>
</body>
</html>
