<!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-03-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>P2322R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2021-03-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="#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="#other-fold-algorithms"><span class="toc-section-number">3</span> Other <code class="sourceCode cpp">fold</code> algorithms<span></span></a>
<ul>
<li><a href="#fold_first"><span class="toc-section-number">3.1</span> <code class="sourceCode cpp">fold_first</code><span></span></a></li>
<li><a href="#fold_right"><span class="toc-section-number">3.2</span> <code class="sourceCode cpp">fold_right</code><span></span></a></li>
<li><a href="#naming"><span class="toc-section-number">3.3</span> Naming<span></span></a></li>
</ul></li>
<li><a href="#wording"><span class="toc-section-number">4</span> Wording<span></span></a></li>
<li><a href="#bibliography"><span class="toc-section-number">5</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="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="other-fold-algorithms"><span class="header-section-number">3</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="3.1" id="fold_first"><span class="header-section-number">3.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>) 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="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-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="cb2-2"><a href="#cb2-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="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-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="cb3-2"><a href="#cb3-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="cb3-3"><a href="#cb3-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="cb3-4"><a href="#cb3-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="cb3-5"><a href="#cb3-5"></a></span>
<span id="cb3-6"><a href="#cb3-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="cb3-7"><a href="#cb3-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="3.2" id="fold_right"><span class="header-section-number">3.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="3.3" id="naming"><span class="header-section-number">3.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="4" style="border-bottom:1px solid #cccccc" id="wording"><span class="header-section-number">4</span> Wording<a href="#wording" class="self-link"></a></h1>
<p>Append to <span>25.4
 <a href="https://wg21.link/algorithm.syn">[algorithm.syn]</a></span>:</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="pp">#include </span><span class="im">&lt;initializer_list&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2"></a></span>
<span id="cb4-3"><a href="#cb4-3"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb4-4"><a href="#cb4-4"></a>  <span class="co">// ...</span></span>
<span id="cb4-5"><a href="#cb4-5"></a>    </span>
<span id="cb4-6"><a href="#cb4-6"></a>  <span class="co">// [alg.fold], folds</span></span>
<span id="cb4-7"><a href="#cb4-7"></a>  <span class="kw">namespace</span> ranges <span class="op">{</span></span>
<span id="cb4-8"><a href="#cb4-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="cb4-9"><a href="#cb4-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="cb4-10"><a href="#cb4-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="cb4-11"><a href="#cb4-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="cb4-12"><a href="#cb4-12"></a>      <span class="op">}</span>;</span>
<span id="cb4-13"><a href="#cb4-13"></a>      </span>
<span id="cb4-14"><a href="#cb4-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="cb4-15"><a href="#cb4-15"></a>    <span class="kw">concept</span> <em>foldable</em> <span class="op">=</span>                        <span class="co">// exposition only</span></span>
<span id="cb4-16"><a href="#cb4-16"></a>      movable<span class="op">&lt;</span>R<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb4-17"><a href="#cb4-17"></a>      copy_constructible<span class="op">&lt;</span>F<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb4-18"><a href="#cb4-18"></a>      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="cb4-19"><a href="#cb4-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="cb4-20"><a href="#cb4-20"></a>  </span>
<span id="cb4-21"><a href="#cb4-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="cb4-22"><a href="#cb4-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="cb4-23"><a href="#cb4-23"></a>      indirectly_readable<span class="op">&lt;</span>I<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb4-24"><a href="#cb4-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="cb4-25"><a href="#cb4-25"></a>      </span>
<span id="cb4-26"><a href="#cb4-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="cb4-27"><a href="#cb4-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="cb4-28"><a href="#cb4-28"></a>      indirectly_readable<span class="op">&lt;</span>I<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></span>
<span id="cb4-29"><a href="#cb4-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="cb4-30"><a href="#cb4-30"></a></span>
<span id="cb4-31"><a href="#cb4-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="cb4-32"><a href="#cb4-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="cb4-33"><a href="#cb4-33"></a>    <span class="kw">constexpr</span> T fold_left<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="cb4-34"><a href="#cb4-34"></a></span>
<span id="cb4-35"><a href="#cb4-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="cb4-36"><a href="#cb4-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="cb4-37"><a href="#cb4-37"></a>    <span class="kw">constexpr</span> T fold_left<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="cb4-38"><a href="#cb4-38"></a></span>
<span id="cb4-39"><a href="#cb4-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="cb4-40"><a href="#cb4-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="cb4-41"><a href="#cb4-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="cb4-42"><a href="#cb4-42"></a>    <span class="kw">constexpr</span> iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span> fold_left<span class="op">(</span>I first, S last, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb4-43"><a href="#cb4-43"></a></span>
<span id="cb4-44"><a href="#cb4-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="cb4-45"><a href="#cb4-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="cb4-46"><a href="#cb4-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="cb4-47"><a href="#cb4-47"></a>    <span class="kw">constexpr</span> range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</span> fold_left<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="cb4-48"><a href="#cb4-48"></a>    </span>
<span id="cb4-49"><a href="#cb4-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="cb4-50"><a href="#cb4-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="cb4-51"><a href="#cb4-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="cb4-52"><a href="#cb4-52"></a></span>
<span id="cb4-53"><a href="#cb4-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="cb4-54"><a href="#cb4-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="cb4-55"><a href="#cb4-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="cb4-56"><a href="#cb4-56"></a></span>
<span id="cb4-57"><a href="#cb4-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="cb4-58"><a href="#cb4-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="cb4-59"><a href="#cb4-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="cb4-60"><a href="#cb4-60"></a>    <span class="kw">constexpr</span> iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span> fold_right<span class="op">(</span>I first, S last, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb4-61"><a href="#cb4-61"></a></span>
<span id="cb4-62"><a href="#cb4-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="cb4-63"><a href="#cb4-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="cb4-64"><a href="#cb4-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="cb4-65"><a href="#cb4-65"></a>    <span class="kw">constexpr</span> range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</span> fold_right<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="cb4-66"><a href="#cb4-66"></a>  <span class="op">}</span></span>
<span id="cb4-67"><a href="#cb4-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="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> T, <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>T, 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">constexpr</span> T ranges<span class="op">::</span>fold_left<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="cb5-4"><a href="#cb5-4"></a></span>
<span id="cb5-5"><a href="#cb5-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="cb5-6"><a href="#cb5-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="cb5-7"><a href="#cb5-7"></a><span class="kw">constexpr</span> T ranges<span class="op">::</span>fold_left<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="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-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="cb6-2"><a href="#cb6-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="cb6-3"><a href="#cb6-3"></a>    <span class="op">++</span>first;</span>
<span id="cb6-4"><a href="#cb6-4"></a><span class="op">}</span></span>
<span id="cb6-5"><a href="#cb6-5"></a><span class="cf">return</span> init;</span></code></pre></div>
</blockquote>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-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="cb7-2"><a href="#cb7-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="cb7-3"><a href="#cb7-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="cb7-4"><a href="#cb7-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_left<span class="op">(</span>I first, S last, BinaryOperation binary_op, Proj proj <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><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="cb7-7"><a href="#cb7-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="cb7-8"><a href="#cb7-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="cb7-9"><a href="#cb7-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_left<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_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>, 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="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> T, <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>T, 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">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="cb8-4"><a href="#cb8-4"></a></span>
<span id="cb8-5"><a href="#cb8-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="cb8-6"><a href="#cb8-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="cb8-7"><a href="#cb8-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="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>next<span class="op">(</span>first, last<span class="op">)</span>;</span>
<span id="cb9-2"><a href="#cb9-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="cb9-3"><a href="#cb9-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="cb9-4"><a href="#cb9-4"></a><span class="op">}</span></span>
<span id="cb9-5"><a href="#cb9-5"></a><span class="cf">return</span> init;</span></code></pre></div>
</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">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="cb10-2"><a href="#cb10-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="cb10-3"><a href="#cb10-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="cb10-4"><a href="#cb10-4"></a><span class="kw">constexpr</span> iter_value_t<span class="op">&lt;</span>I<span class="op">&gt;</span> fold_right<span class="op">(</span>I first, S last, BinaryOperation binary_op, Proj proj <span class="op">=</span> <span class="op">{})</span>;</span>
<span id="cb10-5"><a href="#cb10-5"></a></span>
<span id="cb10-6"><a href="#cb10-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="cb10-7"><a href="#cb10-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="cb10-8"><a href="#cb10-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="cb10-9"><a href="#cb10-9"></a><span class="kw">constexpr</span> range_value_t<span class="op">&lt;</span>R<span class="op">&gt;</span> fold_right<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="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-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="cb11-2"><a href="#cb11-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="5" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">5</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-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>
</div>
</div>
</body>
</html>
