<!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="2024-07-16" />
  <title>Add container pop methods that return the popped value</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.csl-block{margin-left: 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; }
.sourceCode { overflow: visible; }
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 { } 
code span.al { color: #ff0000; } 
code span.an { } 
code span.at { } 
code span.bn { color: #9f6807; } 
code span.bu { color: #9f6807; } 
code span.cf { color: #00607c; } 
code span.ch { color: #9f6807; } 
code span.cn { } 
code span.co { color: #008000; font-style: italic; } 
code span.cv { color: #008000; font-style: italic; } 
code span.do { color: #008000; } 
code span.dt { color: #00607c; } 
code span.dv { color: #9f6807; } 
code span.er { color: #ff0000; font-weight: bold; } 
code span.ex { } 
code span.fl { color: #9f6807; } 
code span.fu { } 
code span.im { } 
code span.in { color: #008000; } 
code span.kw { color: #00607c; } 
code span.op { color: #af1915; } 
code span.ot { } 
code span.pp { color: #6f4e37; } 
code span.re { } 
code span.sc { color: #9f6807; } 
code span.ss { color: #9f6807; } 
code span.st { color: #9f6807; } 
code span.va { } 
code span.vs { color: #9f6807; } 
code span.wa { color: #008000; font-weight: bold; } 
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;
text-align: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}

ul {
list-style-type: none;
padding-left: 2.5em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
ol {
padding-left: 2.5em;
}
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;
}

#TOC ul > li:before {
content: none;
}
#TOC > ul {
padding-left: 0;
}

.toc-section-number {
margin-right: 0.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

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

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

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Add container pop methods
that return the popped value</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3182R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-07-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>
      Brian Bi<br>&lt;<a href="mailto:bbi10@bloomberg.net" class="email">bbi10@bloomberg.net</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#abstract" id="toc-abstract"><span class="toc-section-number">1</span> Abstract</a></li>
<li><a href="#revision-history" id="toc-revision-history"><span class="toc-section-number">2</span> Revision history</a>
<ul>
<li><a href="#r1" id="toc-r1"><span class="toc-section-number">2.1</span> R1</a></li>
</ul></li>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">3</span> Introduction</a></li>
<li><a href="#prevalence" id="toc-prevalence"><span class="toc-section-number">4</span> Prevalence</a></li>
<li><a href="#reasons-for-the-status-quo" id="toc-reasons-for-the-status-quo"><span class="toc-section-number">5</span> Reasons for the status quo</a>
<ul>
<li><a href="#efficiency" id="toc-efficiency"><span class="toc-section-number">5.1</span> Efficiency</a></li>
<li><a href="#exception-safety" id="toc-exception-safety"><span class="toc-section-number">5.2</span> Exception safety</a></li>
</ul></li>
<li><a href="#solution" id="toc-solution"><span class="toc-section-number">6</span> Solution</a>
<ul>
<li><a href="#sequence-containers" id="toc-sequence-containers"><span class="toc-section-number">6.1</span> Sequence containers</a>
<ul>
<li><a href="#move-versus-move_if_noexcept" id="toc-move-versus-move_if_noexcept"><span class="toc-section-number">6.1.1</span>
<code class="sourceCode cpp">move</code> versus
<code class="sourceCode cpp">move_if_noexcept</code></a></li>
</ul></li>
<li><a href="#stdstack-and-stdqueue" id="toc-stdstack-and-stdqueue"><span class="toc-section-number">6.2</span>
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>
and
<code class="sourceCode cpp">std<span class="op">::</span>queue</code></a></li>
<li><a href="#stdpriority_queue" id="toc-stdpriority_queue"><span class="toc-section-number">6.3</span> <code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code></a></li>
</ul></li>
<li><a href="#summary-of-design-decisions" id="toc-summary-of-design-decisions"><span class="toc-section-number">7</span> Summary of design decisions</a>
<ul>
<li><a href="#alternative-names" id="toc-alternative-names"><span class="toc-section-number">7.1</span> Alternative names</a></li>
<li><a href="#exception-safety-1" id="toc-exception-safety-1"><span class="toc-section-number">7.2</span> Exception safety</a></li>
<li><a href="#member-or-free-functions" id="toc-member-or-free-functions"><span class="toc-section-number">7.3</span> Member or free functions</a></li>
<li><a href="#removal-other-than-from-the-end" id="toc-removal-other-than-from-the-end"><span class="toc-section-number">7.4</span> Removal other than from the
end</a></li>
<li><a href="#whether-or-not-to-delegate-to-underlying-container" id="toc-whether-or-not-to-delegate-to-underlying-container"><span class="toc-section-number">7.5</span> Whether or not to delegate to
underlying container</a></li>
</ul></li>
<li><a href="#wording" id="toc-wording"><span class="toc-section-number">8</span> Wording</a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">9</span> References</a></li>
</ul>
</div>
<h1 data-number="1" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>The <code class="sourceCode cpp">pop</code>,
<code class="sourceCode cpp">pop_front</code>, and
<code class="sourceCode cpp">pop_back</code> methods of the Standard
Library containers and container adaptors do not return the value
popped, which is a longstanding pain point for users of the Standard
Library. I discuss how to implement versions of these methods so that
objects are not dropped even when an exception occurs, and propose the
inclusion of these methods in the Standard Library. I also discuss the
special case of <code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code>,
for which failure of a move operation will usually result in
unrecoverable loss of data from <code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code>
even under the status quo; therefore, I also propose the addition of
<code class="sourceCode cpp">std<span class="op">::</span>priority_queue<span class="op">::</span>pop_value</code>.</p>
<h1 data-number="2" id="revision-history"><span class="header-section-number">2</span> Revision history<a href="#revision-history" class="self-link"></a></h1>
<h2 data-number="2.1" id="r1"><span class="header-section-number">2.1</span> R1<a href="#r1" class="self-link"></a></h2>
<ul>
<li>Added sequence containers</li>
<li>Expanded discussion of exception safety</li>
<li>Added discussion of other minor design decisions</li>
<li>Added estimates of the amount of code that could benefit</li>
</ul>
<h1 data-number="3" id="introduction"><span class="header-section-number">3</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>The <code class="sourceCode cpp">pop</code> method appears in three
container adaptors in the C++ Standard Library: namely,
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>,
<code class="sourceCode cpp">std<span class="op">::</span>queue</code>,
and <code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code>.
The return type for each <code class="sourceCode cpp">pop</code> method
is <code class="sourceCode cpp"><span class="dt">void</span></code>; the
popped object is destroyed and its value is not returned to the caller.
Should the programmer wish to obtain the popped value, they must call
the <code class="sourceCode cpp">top</code> or
<code class="sourceCode cpp">front</code> method to obtain a reference
to the object that is about to be popped, move the value of that object
into some other object, and then call
<code class="sourceCode cpp">pop</code>. Thus, idiomatic C++ requires
three statements to accomplish what could be done with one if
<code class="sourceCode cpp">pop</code> were to actually return the
popped value:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Widget <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>stack<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span>      d_stack;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    std<span class="op">::</span>array<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">100</span><span class="op">&gt;</span> d_array;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">// ...</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="dt">int</span> foo<span class="op">()</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>       <span class="co">// other code ...</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>       <span class="co">// invalid:</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a>       <span class="co">// return d_array[d_stack.pop()];</span></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>       <span class="kw">const</span> <span class="kw">auto</span> top <span class="op">=</span> d_stack<span class="op">.</span>top<span class="op">()</span>;</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>       d_stack<span class="op">.</span>pop<span class="op">()</span>;</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>       <span class="cf">return</span> d_stack<span class="op">[</span>top<span class="op">]</span>;</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The fact that <code class="sourceCode cpp">pop</code> does not return
the popped value is a source of widespread annoyance among C++ users and
is bewildering to beginners, particularly those coming from other
languages in which <code class="sourceCode cpp">pop</code>-like methods
do return the popped value, such as Java (<code class="sourceCode cpp">LinkedList<span class="op">.</span>poll</code>,
<code class="sourceCode cpp">PriorityQueue<span class="op">.</span>poll</code>,
etc.), Python
(<code class="sourceCode cpp">list<span class="op">.</span>pop</code>),
JavaScript (<code class="sourceCode cpp">Array<span class="op">.</span>prototype<span class="op">.</span>pop</code>),
and so on.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<p>In the first version of this paper, I proposed to add value-returning
versions of the <code class="sourceCode cpp">pop</code> methods only for
the container adaptors
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>,
<code class="sourceCode cpp">std<span class="op">::</span>queue</code>,
and <code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code>
because my personal experience suggested that these methods would be
most useful for implementing algorithms in which elements are
unconditionally removed and processed in a LIFO, FIFO, or priority-based
order. However, the consensus on the LEWG reflector was that it is rare
for users to use
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>
and
<code class="sourceCode cpp">std<span class="op">::</span>queue</code>
in preference to using sequence containers directly. Therefore, this
revision also proposes the addition of
<code class="sourceCode cpp">pop_front_value</code> and
<code class="sourceCode cpp">pop_back_value</code> to all containers
that have <code class="sourceCode cpp">pop_front</code> and
<code class="sourceCode cpp">pop_back</code>, respectively.</p>
<h1 data-number="4" id="prevalence"><span class="header-section-number">4</span> Prevalence<a href="#prevalence" class="self-link"></a></h1>
<p>Of the roughly 94 million publicly available C++ header and source
files available to search on github.com, I estimate that approximately
220,000 of them contain at least one occurrence of <code class="sourceCode cpp">std<span class="op">::</span>stack<span class="op">::</span>top</code>
followed unconditionally by <code class="sourceCode cpp">std<span class="op">::</span>stack<span class="op">::</span>pop</code>,
where the only code that runs between the two calls can be reordered
after the pop with no change in meaning. The analogous estimate for
<code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code>
is 140,000. These estimates were obtained by examining the first 100
search results for the query <code class="sourceCode cpp"><span class="op">/</span>top\<span class="op">(</span>\<span class="op">).*(</span>\n<span class="op">)?.*</span>pop\<span class="op">(</span>\<span class="op">)/</span> language<span class="op">:</span>C<span class="op">++</span></code>
and manually ruling out false positives such as conditional pops and
assuming that they are representative of the 430,000 matching files
reported by GitHub. The majority of these 360,000 files use stacks and
priority queues in order to implement graph algorithms such as
depth-first search and Dijkstra’s algorithm.</p>
<p>Note that there are an estimated 840,000 files on GitHub that include
the <code class="sourceCode cpp"><span class="op">&lt;</span>stack<span class="op">&gt;</span></code>
header. I don’t think that the ratio of 220,000 to 840,000 should be
taken too seriously because there is not a one-to-one correspondence
between files that use
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>
and files that include the <code class="sourceCode cpp"><span class="op">&lt;</span>stack<span class="op">&gt;</span></code>
header. Nevertheless, I believe the results show that a significant
minority of code that uses
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>
could benefit from a <code class="sourceCode cpp">pop_value</code>
method.</p>
<p>Similarly, there are an estimated 240,000 files on GitHub that call
<code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">::</span>back</code>
followed unconditionally by <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">::</span>pop_back</code>
(and much smaller numbers for
<code class="sourceCode cpp">std<span class="op">::</span>deque</code>,
<code class="sourceCode cpp">std<span class="op">::</span>list</code>,
and
<code class="sourceCode cpp">std<span class="op">::</span>string</code>),
compared with 7,500,000 files that include the <code class="sourceCode cpp"><span class="op">&lt;</span>vector<span class="op">&gt;</span></code>
header. These results confirm an assertion I made on the Library
Evolution reflector that, although
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
is used far more than the container adaptors, the
peek-and-unconditionally-pop operation is a far more significant use
case for container adaptors than containers.</p>
<h1 data-number="5" id="reasons-for-the-status-quo"><span class="header-section-number">5</span> Reasons for the status quo<a href="#reasons-for-the-status-quo" class="self-link"></a></h1>
<h2 data-number="5.1" id="efficiency"><span class="header-section-number">5.1</span> Efficiency<a href="#efficiency" class="self-link"></a></h2>
<p>The
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>,
<code class="sourceCode cpp">std<span class="op">::</span>queue</code>,
and <code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code>
container adaptors, like many other components of the C++ Standard
Library, were inspired by SGI’s Standard Template Library (STL). The STL
documentation <span class="citation" data-cites="STL">[<a href="http://web.archive.org/web/20010221200527/http://www.sgi.com/tech/stl/stack.html" role="doc-biblioref">STL</a>]</span> explains why separate
<code class="sourceCode cpp">top</code>/<code class="sourceCode cpp">front</code>
and <code class="sourceCode cpp">pop</code> methods are provided:
<code class="sourceCode cpp">pop</code> cannot return by reference since
the reference would dangle, but returning by value would impose on the
user the cost of copying the object. Because imposing this cost would be
undesirable, I do not propose to change the existing
<code class="sourceCode cpp">pop</code> methods to return the popped
value, but instead propose a new
<code class="sourceCode cpp">pop_value</code> method. In modern C++, the
cost of calling <code class="sourceCode cpp">pop_value</code> will
typically be minimal due to move semantics. For example, here is a
possible implementation of <code class="sourceCode cpp">std<span class="op">::</span>stack<span class="op">::</span>pop_value</code>:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>value_type pop_value<span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    value_type x <span class="op">=</span> move<span class="op">(</span>top<span class="op">())</span>;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    pop<span class="op">()</span>;</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> x;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In the above implementation, NRVO allows
<code class="sourceCode cpp">x</code> to be treated as an alias for the
returned object (§<span>11.9.6
<a href="https://wg21.link/N4981#class.copy.elision">[class.copy.elision]</a><a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></span>p1.1 of the Standard). GCC
always performs this optimization by default and Clang performs it at
<code class="sourceCode cpp"><span class="op">-</span>O1</code> and
higher (but both permit the user to explicitly disable it using the
<code class="sourceCode cpp"><span class="op">-</span>fno<span class="op">-</span>elide<span class="op">-</span>constructors</code>
flag). When NRVO is performed, a single call to
<code class="sourceCode cpp">value_type</code>’s move constructor occurs
when <code class="sourceCode cpp">pop_value</code> is called. When NRVO
is not performed, the move constructor is called twice (§<span>7.5.4.2
<a href="https://wg21.link/N4981#expr.prim.id.unqual">[expr.prim.id.unqual]</a></span>).</p>
<p>The considerations above also apply to the sequence containers (other
than
<code class="sourceCode cpp">std<span class="op">::</span>array</code>,
which cannot be popped from because its size is fixed): the introduction
of new methods alongside the existing
<code class="sourceCode cpp">pop_front</code> and
<code class="sourceCode cpp">pop_back</code> methods, together with the
use of move semantics, would allow users to pop and get the popped value
at the same time, without incurring the performance penalties outlined
by the SGI STL documentation.</p>
<h2 data-number="5.2" id="exception-safety"><span class="header-section-number">5.2</span> Exception safety<a href="#exception-safety" class="self-link"></a></h2>
<p>The more well-known reason for
<code class="sourceCode cpp">pop</code> not returning the popped value
is the issue of exception safety. In the implementation of
<code class="sourceCode cpp">pop_value</code> above, although NRVO will
often be performed, it is not guaranteed. Now suppose that NRVO is not
performed. Then, the returned object is initialized by moving from
<code class="sourceCode cpp">x</code>. If this move operation exits via
an exception, it is impossible to provide the strong exception safety
guarantee even if <code class="sourceCode cpp">value_type</code>’s move
constructor provides it. In order to restore the state of the stack or
queue as it existed prior to the call to
<code class="sourceCode cpp">pop_value</code>, the popped object would
need to be put back at the top of the stack or the front of the queue.
This operation cannot be accomplished without calling the move
constructor again (<em>i.e.</em>, the very operation that has just
failed). Therefore, the only choice is to destroy the popped object and
propagate the exception. The object popped is thus “dropped” and its
value is lost forever.</p>
<h1 data-number="6" id="solution"><span class="header-section-number">6</span> Solution<a href="#solution" class="self-link"></a></h1>
<h2 data-number="6.1" id="sequence-containers"><span class="header-section-number">6.1</span> Sequence containers<a href="#sequence-containers" class="self-link"></a></h2>
<p>It is possible to implement <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>T<span class="op">&gt;::</span>pop_back_value</code>
so that it provides the same exception safety guarantee as moving from
<code class="sourceCode cpp">back</code> and then calling
<code class="sourceCode cpp">pop_back</code> upon success, and,
therefore, does not drop elements when
<code class="sourceCode cpp">T</code>’s move constructor throws. The
following is a proof-of-concept implementation that works for any
sequence container that provides
<code class="sourceCode cpp">pop_back</code>. The implementation for
<code class="sourceCode cpp">pop_front_value</code> is very similar but
uses <code class="sourceCode cpp">front<span class="op">()</span></code>
and
<code class="sourceCode cpp">pop_front<span class="op">()</span></code>
instead of
<code class="sourceCode cpp">back<span class="op">()</span></code> and
<code class="sourceCode cpp">pop_back<span class="op">()</span></code>.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>value_type pop_value<span class="op">()</span> <span class="op">{</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> Guard <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>        vector<span class="op">*</span> __this;</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        <span class="dt">bool</span> failure <span class="op">=</span> <span class="kw">false</span>;</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">~</span>Guard<span class="op">()</span> <span class="kw">noexcept</span><span class="op">(</span><span class="kw">false</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>            <span class="cf">if</span> <span class="op">(!</span>failure<span class="op">)</span> <span class="op">{</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>                __this<span class="op">-&gt;</span>pop_back<span class="op">()</span>;</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>            <span class="op">}</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> guard<span class="op">{</span><span class="kw">this</span><span class="op">}</span>;</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">try</span> <span class="op">{</span></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> move<span class="op">(</span>back<span class="op">())</span>;</span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> <span class="cf">catch</span> <span class="op">(...)</span> <span class="op">{</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true" tabindex="-1"></a>        guard<span class="op">.</span>failure <span class="op">=</span> <span class="kw">true</span>;</span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">throw</span>;</span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In this implementation, only a single move occurs, even if the
compiler declines to perform NRVO. Thus, there is only a single point
where we must pay attention to the possibility of a move constructor
exiting by throwing an exception. Note that it is the caller’s
responsibility to ensure that the popped value is not lost
<em>after</em> <code class="sourceCode cpp">pop_back_value</code>
returns. For example:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> foo<span class="op">(</span>std<span class="op">::</span>vector<span class="op">&lt;</span>Widget<span class="op">&gt;&amp;</span> s<span class="op">)</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    Widget w <span class="op">=</span> s<span class="op">.</span>pop_back_value<span class="op">()</span>;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">// do something with `w` ...</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    w <span class="op">=</span> s<span class="op">.</span>pop_back_value<span class="op">()</span>;</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In the above code, due to guaranteed copy elision <span class="citation" data-cites="P0135R1">[<a href="https://wg21.link/p0135r1" role="doc-biblioref">P0135R1</a>]</span>, the object stored in
<code class="sourceCode cpp">s</code> is moved directly into the local
variable <code class="sourceCode cpp">w</code> when
<code class="sourceCode cpp">w</code> is initialized. If this move
operation succeeds, the moved-from object is popped from
<code class="sourceCode cpp">s</code>. If the move operation fails by
throwing an exception, a flag is set and the destruction of
<code class="sourceCode cpp">guard</code> does not attempt to remove the
object from <code class="sourceCode cpp">s</code>. Therefore, if
<code class="sourceCode cpp">value_type</code>’s move constructor
provides the strong exception safety guarantee, then the
<code class="sourceCode cpp">pop_back_value</code> implementation above
provides the same guarantee. If
<code class="sourceCode cpp">value_type</code>’s move constructor
provides the basic exception safety guarantee, then
<code class="sourceCode cpp">pop_back_value</code> provides the basic
exception safety guarantee in that the vector remains in a valid state,
and additionally guarantees that the item at the back of the vector is
not lost (though its original value might not be recoverable).</p>
<p>However, if the move assignment operator of
<code class="sourceCode cpp">Widget</code> throws after the second call
to <code class="sourceCode cpp">pop_back_value</code>, then, even if
that operator provides the strong exception safety guarantee, the
temporary object materialized from <code class="sourceCode cpp">s<span class="op">.</span>pop_back_value<span class="op">()</span></code>,
which still holds the popped value, will be destroyed and the value will
be lost. If the caller of
<code class="sourceCode cpp">pop_back_value</code> is able to recover
from a move operation that throws, then the caller can avoid dropping
the popped value by declaring another local variable to hold the popped
value before calling the move assignment operator. Of course, such
concerns need not trouble a user who has provided
<code class="sourceCode cpp">Widget</code> with a non-throwing move
assignment operator.</p>
<p>Note that the above implementation is simply a proof-of-concept; one
optimization that I anticipate library implementors wanting to make (but
that is not necessary to specify in the Standard) is that if <code class="sourceCode cpp">std<span class="op">::</span>is_nothrow_move_constructible_v<span class="op">&lt;</span>value_type<span class="op">&gt;</span></code>
is true, then the try/catch block and the
<code class="sourceCode cpp">failure</code> variable can be omitted.</p>
<h3 data-number="6.1.1" id="move-versus-move_if_noexcept"><span class="header-section-number">6.1.1</span>
<code class="sourceCode cpp">move</code> versus
<code class="sourceCode cpp">move_if_noexcept</code><a href="#move-versus-move_if_noexcept" class="self-link"></a></h3>
<p>In cases where <code class="sourceCode cpp">value_type</code>’s move
constructor is not
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>,
there is a question of whether the implementation of <code class="sourceCode cpp">pop_<span class="op">(</span>front<span class="op">|</span>back<span class="op">)</span>_value</code>
should call
<code class="sourceCode cpp">std<span class="op">::</span>move</code> or
<code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>.</p>
<p>The most well-known usage of <code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>
is by
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
when reallocating. Copying, rather than moving, objects with throwing
move constructors during reallocation enables
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
to provide the strong exception safety guarantee for some operations
that may reallocate.</p>
<p>For the proposed <code class="sourceCode cpp">pop_<span class="op">(</span>front<span class="op">|</span>back<span class="op">)</span>_value</code>
methods of sequence containers, it is also possible to provide the
strong exception guarantee unconditionally (<em>i.e.</em>, regardless of
what <code class="sourceCode cpp">value_type</code> is) by using <code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>
instead of
<code class="sourceCode cpp">std<span class="op">::</span>move</code>.
However, using <code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>
also has a cost because it results in possibly unexpected and expensive
copies for reasons that are unfamiliar even to many experienced C++
programmers. For example, consider an implementation in which
<code class="sourceCode cpp">std<span class="op">::</span>deque</code>
does not have a
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
move cosntructor. If <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">::</span>pop_back_value</code>
uses <code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>,
then on such an implementation:</p>
<ul>
<li>A call to <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>deque<span class="op">&lt;</span>T<span class="op">&gt;&gt;::</span>pop_back_value</code>
will not compile if <code class="sourceCode cpp">T</code> is a move-only
type such as <code class="sourceCode cpp">std<span class="op">::</span>unique_ptr<span class="op">&lt;</span>U<span class="op">&gt;</span></code>.</li>
<li>A call to <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">&lt;</span>std<span class="op">::</span>deque<span class="op">&lt;</span>T<span class="op">&gt;&gt;::</span>pop_back_value</code>
will perform a copy in order to initialize each returned <code class="sourceCode cpp">std<span class="op">::</span>deque<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
object.</li>
</ul>
<p>In the first case, a beginner will find it difficult to understand
why seemingly reasonable code does not compile. In the second case, a
beginner will write code that performs worse than expected, and may find
it very difficult to even recognize the possibility that the performance
is due to the implementation making an implicit choice to perform
copies.</p>
<p>It has been suggested that failing to provide strong exception safety
creates a trap for beginners because the value of the popped item may
not be recoverable in the event that the popped item’s move constructor
only provides the basic exception safety guarantee. I believe that the
current Standard Library is already a trap for beginners in that sense,
because it contains a large number of functions that are either not
strongly exception-safe or that provide strong exception safety only
under certain circumstances. For example, most functions that pop a
single element are strongly exception-safe, but <code class="sourceCode cpp">std<span class="op">::</span>priority_queue<span class="op">&lt;</span>T<span class="op">&gt;::</span>pop</code>
is not; functions that insert a single element at the end of a
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>
or
<code class="sourceCode cpp">std<span class="op">::</span>deque</code>
(but not the middle) are strongly exception-safe if the element type is
copyable or has a non-throwing move constructor, but not otherwise; and
functions that insert or remove several objects at once are usually not
strongly exception-safe, but they are in the case of
<code class="sourceCode cpp">std<span class="op">::</span>list</code>.
In any moderately complex application that makes use of the Standard
Library, it is extremely unlikely that a beginner would, simply through
sheer luck, avoid losing data along all paths in which a Standard
Library function exits via an exception; the Standard Library is simply
too riddled with traps for anyone to dodge all of them except through
constant vigilance. In order to write a correct program whose
correctness depends on the strong exception safety guarantees of the
Standard Library, it is necessary to investigate every Standard Library
function individually, understand the circumstances in which it is
strongly exception-safe, and use (or avoid) it accordingly.</p>
<p>Programmers who are aware of the fact that a variety of different
exception safety guarantees are present in the Standard Library, and who
have the level of understanding required to avoid calling Standard
Library functions in ways that are not strongly exception safe, will not
be burdened by the presence of
<code class="sourceCode cpp">pop_value</code>,
<code class="sourceCode cpp">pop_front_value</code>, and
<code class="sourceCode cpp">pop_back_value</code> methods; their
<em>modus operandi</em> is necessarily to avoid any new functions until
they have researched their exception safety guarantees. All other
programmers are already not writing correct programs when their logical
correctness depends on the strong exception safety guarantees in the
Standard Library; if the possible loss of data for such programmers is
untenable, they must be preventing it using drastic measures such as
disabling exceptions or completely avoiding the usage of the Standard
Library.</p>
<p>Therefore, the cost/benefit analysis for beginner C++ programmers
favors the use of
<code class="sourceCode cpp">std<span class="op">::</span>move</code>
instead of <code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>:
the former avoids confusing compilation errors and degradation of
performance, and does not significantly worsen the status quo in which
beginners who use the Standard Library together with exceptions cannot
avoid data loss except in the unlikely event that they carefully
research each Standard Library function’s exception safety guarantees
prior to using it.</p>
<p>Experts who desire strong exception safety would be better served by
the implicit use of <code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>
than
<code class="sourceCode cpp">std<span class="op">::</span>move</code>,
but there are also experts for whom strong exception safety is not
important. To evaluate the impact of this design decision on experts, we
need to consider the cost to the expert to obtain the desired behavior
when a Standard Library function provides the opposite one. If
<code class="sourceCode cpp">pop_back_value</code> uses
<code class="sourceCode cpp">std<span class="op">::</span>move</code>
but an expert wants strong exception safety, they can simply continue
writing the sequence of <code class="sourceCode cpp">move_if_noexcept<span class="op">(</span>back<span class="op">())</span></code>
followed by
<code class="sourceCode cpp">pop_back<span class="op">()</span></code>
that they are likely currently using. If
<code class="sourceCode cpp">pop_back_value</code> uses <code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>
but an expert wants an unconditional move, they can implement a
non-member <code class="sourceCode cpp">pop_back_value</code> that moves
unconditionally using one of the two approaches above. The burden is not
huge in either case, but I think there are more experts who don’t need
strong exception safety than ones who do.</p>
<p>Lastly, I believe there are two differences from vector reallocation
that suggest that
<code class="sourceCode cpp">std<span class="op">::</span>move</code> is
a better choice in the
<code class="sourceCode cpp">pop_back_value</code> case than in the
<code class="sourceCode cpp">push_back</code> case:</p>
<ol type="1">
<li><code class="sourceCode cpp">pop_back_value</code> uses only a
<em>single</em> call to the move constructor; therefore, if
<code class="sourceCode cpp">pop_back_value</code> uses
<code class="sourceCode cpp">std<span class="op">::</span>move</code>,
it inherits the exception safety guarantee from
<code class="sourceCode cpp">T</code>’s move constructor: in other
words, if <code class="sourceCode cpp">T</code>’s move constructor
provides the strong exception safety guarantee, then so does
<code class="sourceCode cpp">pop_back_value</code>. The same is not true
for vector reallocation.</li>
<li>In cases where the user needs strong exception safety
unconditionally (<em>i.e.</em>, even when
<code class="sourceCode cpp">T</code>’s move constructor is not known to
provide the strong exception safety guarantee), there is a simple
workaround discussed above. In contrast, if vector reallocation were to
use
<code class="sourceCode cpp">std<span class="op">::</span>move</code>,
it would be much more inconvenient for the user to recover the strong
exception safety guarantee. <a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></li>
</ol>
<h2 data-number="6.2" id="stdstack-and-stdqueue"><span class="header-section-number">6.2</span>
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>
and
<code class="sourceCode cpp">std<span class="op">::</span>queue</code><a href="#stdstack-and-stdqueue" class="self-link"></a></h2>
<p>To implement <code class="sourceCode cpp">std<span class="op">::</span>stack<span class="op">::</span>pop_value</code>,
there are two options. One is to delegate the entire operation to the
underlying container, <em>e.g.</em>, the body can simply be <code class="sourceCode cpp"><span class="cf">return</span> c<span class="op">.</span>pop_back_value<span class="op">()</span>;</code>.
The other is to call <code class="sourceCode cpp"><span class="cf">return</span> move<span class="op">(</span>top<span class="op">())</span></code>
and then call
<code class="sourceCode cpp">pop<span class="op">()</span></code> in the
destructor of a guard variable if the former was successful, similarly
to the possible implementation shown above for <code class="sourceCode cpp">std<span class="op">::</span>vector<span class="op">::</span>pop_back_value<span class="op">()</span></code>.</p>
<p>When
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>
wraps a Standard Library sequence container (as it does by default),
there is no difference in behavior between these two implementation
strategies for the stack’s <code class="sourceCode cpp">pop_value</code>
method. They differ in the case where
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>
wraps a user-defined container that does not provide
<code class="sourceCode cpp">pop_back_value</code> or, perhaps, provides
only <code class="sourceCode cpp">pop_back_value</code> and not
<code class="sourceCode cpp">back</code> (which could be the case for a
concurrent data structure).</p>
<p>I propose that the <code class="sourceCode cpp">pop_value</code>
method of
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>
call the underlying container’s
<code class="sourceCode cpp">pop_back_value</code> methods for the
following reasons:</p>
<ul>
<li>If <code class="sourceCode cpp">pop_back_value</code> is provided by
the underlying container but <code class="sourceCode cpp">back</code>
itself is not, then a <code class="sourceCode cpp">pop_value</code> that
calls <code class="sourceCode cpp">pop_back_value</code> will be the
only way to remove and process the values stored in the
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>.</li>
<li>If the container supports both
<code class="sourceCode cpp">pop_back_value</code> and
<code class="sourceCode cpp">back</code> but with different behavior,
then a container adaptor <code class="sourceCode cpp">pop_value</code>
that calls the former follows the principle of least surprise.</li>
</ul>
<p>Similarly, I propose that <code class="sourceCode cpp">std<span class="op">::</span>queue<span class="op">::</span>pop</code>
call the underlying container’s
<code class="sourceCode cpp">pop_front_value</code> method.</p>
<p>The strategy of calling
<code class="sourceCode cpp">top<span class="op">()</span></code>
followed by
<code class="sourceCode cpp">pop<span class="op">()</span></code> raises
an additional design question: what should happen when
<code class="sourceCode cpp">pop<span class="op">()</span></code> throws
an exception because the underlying container’s
<code class="sourceCode cpp">pop_back</code> method throws an exception?
Such a scenario cannot arise when the underlying container is a Standard
Library container<a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a>, but this requirement has never been
imposed on user-defined containers that are used to instantiate a
container adaptor. Revision 0 of this paper <span class="citation" data-cites="P3182R0">[<a href="https://wg21.link/p3182r0" role="doc-biblioref">P3182R0</a>]</span> analyzed several options for
dealing with a throwing <code class="sourceCode cpp">pop_back</code>,
which are not repeated in this revision.</p>
<p>It is conceivable for <code class="sourceCode cpp">std<span class="op">::</span>stack<span class="op">::</span>pop_value</code>
to call <code class="sourceCode cpp">c<span class="op">.</span>pop_back_value<span class="op">()</span></code>
when that expression is well formed, and otherwise fall back to an
implementation that calls
<code class="sourceCode cpp">top<span class="op">()</span></code> and
<code class="sourceCode cpp">pop<span class="op">()</span></code>.
Having <code class="sourceCode cpp">pop_value</code> unconditionally
call <code class="sourceCode cpp">c<span class="op">.</span>pop_back_value<span class="op">()</span></code>
(and be unavailable when <code class="sourceCode cpp">c</code> does not
provide <code class="sourceCode cpp">pop_back_value</code>) leaves open
the possibility of introducing such a fallback in the future if
consensus can be achieved on how to deal with a throwing
<code class="sourceCode cpp">pop_back</code>.</p>
<h2 data-number="6.3" id="stdpriority_queue"><span class="header-section-number">6.3</span> <code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code><a href="#stdpriority_queue" class="self-link"></a></h2>
<p>The case of <code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code>
is very different. It is not possible to move from the top of a heap
without compromising the heap’s invariant, so <code class="sourceCode cpp">std<span class="op">::</span>pop_heap</code> must
be called on the underlying container before the returned object can be
initialized. In general, <code class="sourceCode cpp">std<span class="op">::</span>pop_heap</code> will
use a number of move operations that is approximately logarithmic in the
current size of the heap, and if any such operation besides the first
throws an exception, the heap will be left in an invalid state. This
risk also exists in the status quo: although the user will call
<code class="sourceCode cpp">top</code> first and
<code class="sourceCode cpp">pop</code> afterward, a failure in <code class="sourceCode cpp">std<span class="op">::</span>pop_heap</code>
during the second step will make it impossible to extract any further
data safely from the <code class="sourceCode cpp">priority_queue</code>.
Therefore, <code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code>
is inherently unreliable in the presence of throwing moves. For this
reason, I think that the possibility of throwing moves is no rationale
for omitting <code class="sourceCode cpp">pop_value</code> from <code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code>.
Furthermore, if a move operation were to throw, then it is more likely
for the exception to occur during the
<code class="sourceCode cpp">pop_heap</code> step than the
initialization of the return object. Therefore, I consider it
unnecessary to provide a guarantee about the state of the
<code class="sourceCode cpp">priority_queue</code> even if the final
move throws; the caller cannot tell whether the exception originated
from the <code class="sourceCode cpp">pop_heap</code> step, and
therefore, cannot rely on any such guarantee. For example, a conforming
implementation need not check whether the final move succeeded:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>value_type pop_value<span class="op">()</span> <span class="op">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    pop_heap<span class="op">(</span>c<span class="op">.</span>begin<span class="op">()</span>, c<span class="op">.</span>end<span class="op">()</span>, comp<span class="op">)</span>;</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> Guard <span class="op">{</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>        priority_queue<span class="op">*</span> __this;</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>        <span class="op">~</span>Guard<span class="op">()</span> <span class="kw">noexcept</span><span class="op">(</span><span class="kw">false</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>            __this<span class="op">-&gt;</span>c<span class="op">.</span>pop_back<span class="op">()</span>;</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span> guard<span class="op">{</span><span class="kw">this</span><span class="op">}</span>;</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> move<span class="op">(</span>c<span class="op">.</span>back<span class="op">())</span>;</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h1 data-number="7" id="summary-of-design-decisions"><span class="header-section-number">7</span> Summary of design decisions<a href="#summary-of-design-decisions" class="self-link"></a></h1>
<p>This section summarizes design decisions that may be controversial or
otherwise merit special consideration from the LEWG. Some of these
design decisions have been discussed in more depth earlier in this
paper.</p>
<h2 data-number="7.1" id="alternative-names"><span class="header-section-number">7.1</span> Alternative names<a href="#alternative-names" class="self-link"></a></h2>
<p>For the container adaptors, the name
<code class="sourceCode cpp">pop_value</code> was suggested by Lauri
Vasama. Other possible names include
<code class="sourceCode cpp">pop_and_get</code> and
<code class="sourceCode cpp">pop_and_return</code>. For the sequence
containers, I propose the names
<code class="sourceCode cpp">pop_front_value</code> and
<code class="sourceCode cpp">pop_back_value</code> in analogy with
<code class="sourceCode cpp">pop_value</code>. Arthur O’Dwyer has
implemented similar methods named
<code class="sourceCode cpp">displace</code>,
<code class="sourceCode cpp">displace_back</code>,
<code class="sourceCode cpp">displace_top</code>, etc. I consider
<code class="sourceCode cpp">pop_value</code> and its variants to be a
slightly better name than <code class="sourceCode cpp">displace</code>
and its variants because, when a container has both a
<code class="sourceCode cpp">pop</code> and a
<code class="sourceCode cpp">displace</code> method, it will not be
obvious to the user which one returns a value and which does not.
However, one argument in favor of
<code class="sourceCode cpp">displace</code> is that constructions such
as <code class="sourceCode cpp">displace_back</code> are less awkward
than <code class="sourceCode cpp">pop_back_value</code>. Indeed, a user
might forget whether the word <code class="sourceCode cpp">back</code>
or the word <code class="sourceCode cpp">value</code> goes first. The
reason I propose <code class="sourceCode cpp">pop_front_value</code>
instead of <code class="sourceCode cpp">pop_value_front</code> is that,
by placing the word <code class="sourceCode cpp">value</code> at the end
rather than between <code class="sourceCode cpp">pop</code> and
<code class="sourceCode cpp">front</code>, we emphasize that
<code class="sourceCode cpp">pop_front_value</code> does the same thing
as <code class="sourceCode cpp">pop_front</code>, with the only
difference being that a value is returned. I admit that this is not a
particularly compelling reason, and I am not opposed to the name
<code class="sourceCode cpp">pop_value_front</code>.</p>
<h2 data-number="7.2" id="exception-safety-1"><span class="header-section-number">7.2</span> Exception safety<a href="#exception-safety-1" class="self-link"></a></h2>
<p>This paper currently proposes the usage of
<code class="sourceCode cpp">std<span class="op">::</span>move</code>
rather than <code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>,
as discussed in Section 5.1.2. If the LEWG polls to encourage the usage
of <code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>
instead, this paper will be updated to propose that.</p>
<p>A suggestion was made on the LEWG reflector that the Standard Library
could benefit from a trait that indicates whether the move construction
of a given type is strongly exception-safe. The trait would
automatically be true for all scalar types and all types that are
nothrow move constructible, but other types could opt into the trait,
such as a
<code class="sourceCode cpp">std<span class="op">::</span>list</code>
implementation that always attempts to allocate a head node for the
moved-from object first, before proceeding to an operation that cannot
fail (<em>i.e.</em>, swapping the head node pointers of the source and
destination). If such a trait were available, then
<code class="sourceCode cpp">pop_value</code> methods (other than for
<code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code>)
could be made strongly exception safe by using the move constructor when
the move constructor is strongly exception-safe, and the copy
constructor otherwise.</p>
<p>This paper does not actually propose a trait for strong exception
safety of move construction. However, the possibility of such a
direction suggests a third design option for this paper, namely to
provide the proposed methods only when the element type is nothrow move
constructible. Such a design, despite having the unfortunate effect of
making the methods unavailable in certain cases in which users would
expect them to be available, would maximize forward compatibility with a
future design based on the trait described above.</p>
<h2 data-number="7.3" id="member-or-free-functions"><span class="header-section-number">7.3</span> Member or free functions<a href="#member-or-free-functions" class="self-link"></a></h2>
<p>It was suggested on the LEWG reflector that I explain why I propose
that the <code class="sourceCode cpp">pop_value</code> functions be
added as member functions rather than free functions. The LEWG does not
currently have a policy that would help to make this decision. I note,
however, that in the case of the container adaptors, the proposed
semantics require at least protected access to the container adaptor,
since a <code class="sourceCode cpp">pop_<span class="op">(</span>front<span class="op">|</span>back<span class="op">)</span>_value</code>
method must be called on the protected member
<code class="sourceCode cpp">c</code>. Generally, operations on Standard
Library types that cannot be implemented correctly without recourse to
the non-public interface are made member functions, except in the case
of operators and <code class="sourceCode cpp">swap</code> functions,
which are sometimes friends. In the case of the sequence containers,
non-public access is not required, and Meyers’s algorithm <span class="citation" data-cites="meyers00">[<a href="https://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197" role="doc-biblioref">meyers00</a>]</span> would therefore indicate a
non-friend free function. However, Meyers’s algorithm is generally not
followed by the Standard Library. While I would personally support a
LEWG policy that is more in line with Meyers’s algorithm, one does not
currently exist, so I propose member functions for consistency with the
rest of the container operations in the Standard Library.</p>
<h2 data-number="7.4" id="removal-other-than-from-the-end"><span class="header-section-number">7.4</span> Removal other than from the
end<a href="#removal-other-than-from-the-end" class="self-link"></a></h2>
<p>Although methods that remove an element from the middle of a sequence
container are not named with <code class="sourceCode cpp">pop</code>, it
is conceivable that a user might want a variation of
<code class="sourceCode cpp">erase</code> that returns the element
removed. Similarly, a user might want such methods for associative and
unordered associative containers. I do not currently propose
<code class="sourceCode cpp">erase_value</code> methods because I
believe that methods that return the removed value are most often useful
for implementing algorithms in which elements are unconditionally
removed (<em>i.e.</em> without first looking at the value) and processed
in a LIFO, FIFO, or priority-based order. I do not take a position here
on whether <code class="sourceCode cpp">erase_value</code> methods
should be added to the Standard Library by a separate proposal.</p>
<h2 data-number="7.5" id="whether-or-not-to-delegate-to-underlying-container"><span class="header-section-number">7.5</span> Whether or not to delegate to
underlying container<a href="#whether-or-not-to-delegate-to-underlying-container" class="self-link"></a></h2>
<p>As discussed in Section 5.2, this paper proposes that container
adaptors’ <code class="sourceCode cpp">pop_value</code> methods delegate
to the underlying containers’
<code class="sourceCode cpp">pop_back_value</code> and
<code class="sourceCode cpp">pop_front_value</code> methods instead of
calling <code class="sourceCode cpp">top</code> followed by
<code class="sourceCode cpp">pop_back</code> or
<code class="sourceCode cpp">front</code> followed by
<code class="sourceCode cpp">pop_front</code>.</p>
<h1 data-number="8" id="wording"><span class="header-section-number">8</span> Wording<a href="#wording" class="self-link"></a></h1>
<p>The proposed wording is relative to <span class="citation" data-cites="N4981">[<a href="https://wg21.link/n4981" role="doc-biblioref">N4981</a>]</span>.</p>
<p>Modify §<span>9.4.5
<a href="https://wg21.link/N4981#dcl.init.list">[dcl.init.list]</a></span>p1:</p>
<blockquote>
<p>[…] List-initialization can occur in direct-initialization or
copy-initialization contexts; list-initialization in a
direct-initialization context is called
<em>direct-list-initialization</em> and list-initialization in a
copy-initialization context is called <em>copy-list-initialization</em>.
Direct-initialization that is not list-initialization is called
<em>direct-non-list-initialization</em><span class="add" style="color: #006e28"><ins>; copy-initialization that is not
list-initialization is called
<em>copy-non-list-initialization</em></ins></span>.<br />
[…]</p>
</blockquote>
<p>Modify §<span>23.4.3.1
<a href="https://wg21.link/N4981#basic.string.general">[basic.string.general]</a></span>p3:</p>
<blockquote>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">void</span> pop_back<span class="op">()</span>;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>constexpr charT pop_back_value();</ins></span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Modify §<span>24.2.4
<a href="https://wg21.link/N4981#sequence.reqmts">[sequence.reqmts]</a></span>
by inserting the following after paragraph 112:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="sourceCode" id="cb7"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>a.pop_front_value()</span></code></pre></div>
<p><em>Result</em>: <code class="sourceCode default">T</code></p>
<p><em>Preconditions</em>:
<code class="sourceCode default">a.empty()</code> is
<code class="sourceCode default">false</code> and
<code class="sourceCode default">T</code> is
<em>Cpp17MoveConstructible</em>.</p>
<p><em>Effects</em>: Copy-non-list-initializes the return object from
<code class="sourceCode default">std::move(front())</code>, then calls
<code class="sourceCode default">pop_front</code>.</p>
<p><em>Remarks</em>: Required for
<code class="sourceCode default">deque</code>,
<code class="sourceCode default">forward_list</code>, and
<code class="sourceCode default">list</code>.</p>
</blockquote>

</div>
<p>Modify §<span>24.2.4
<a href="https://wg21.link/N4981#sequence.reqmts">[sequence.reqmts]</a></span>
by inserting the following after paragraph 116:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>a.pop_back_value()</span></code></pre></div>
<p><em>Result</em>: <code class="sourceCode default">T</code></p>
<p><em>Preconditions</em>:
<code class="sourceCode default">a.empty()</code> is
<code class="sourceCode default">false</code> and
<code class="sourceCode default">T</code> is
<em>Cpp17MoveConstructible</em>.</p>
<p><em>Effects</em>: Copy-non-list-initializes the return object from
<code class="sourceCode default">std::move(back())</code>, then calls
<code class="sourceCode default">pop_back</code>.</p>
<p><em>Remarks</em>: Required for
<code class="sourceCode default">basic_string</code>,
<code class="sourceCode default">deque</code>,
<code class="sourceCode default">list</code>, and
<code class="sourceCode default">vector</code>.</p>
</blockquote>

</div>
<p>Modify §<span>24.3.8.1
<a href="https://wg21.link/N4981#deque.overview">[deque.overview]</a></span>p2:</p>
<blockquote>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> pop_front<span class="op">()</span>;</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>T pop_front_value();</ins></span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> pop_back<span class="op">()</span>;</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>T pop_back_value();</ins></span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Modify §<span>24.3.9.1
<a href="https://wg21.link/N4981#forward.list.overview">[forward.list.overview]</a></span>p3:</p>
<blockquote>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> pop_front<span class="op">()</span>;</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>T pop_front_value();</ins></span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Modify §<span>24.3.10.1
<a href="https://wg21.link/N4981#list.overview">[list.overview]</a></span>p2:</p>
<blockquote>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> pop_front<span class="op">()</span>;</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>T pop_front_value();</ins></span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> push_back<span class="op">(</span><span class="kw">const</span> T<span class="op">&amp;</span> x<span class="op">)</span>;</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> pop_back<span class="op">()</span>;</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>T pop_back_value();</ins></span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Modify §<span>24.3.11.1
<a href="https://wg21.link/N4981#vector.overview">[vector.overview]</a></span>p3:</p>
<blockquote>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">void</span> pop_back<span class="op">()</span>;</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>constexpr T pop_back_value();</ins></span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Modify §<span>24.3.12.1
<a href="https://wg21.link/N4981#vector.bool.pspc">[vector.bool.pspc]</a></span>p1:</p>
<blockquote>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">void</span> pop_back<span class="op">()</span>;</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>constexpr bool pop_back_value();</ins></span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Modify §<span>24.6.6.1
<a href="https://wg21.link/N4981#queue.defn">[queue.defn]</a></span>p1:</p>
<blockquote>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> pop<span class="op">()</span>                          <span class="op">{</span> c<span class="op">.</span>pop_front<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>value_type pop_value();</ins></span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> swap<span class="op">(</span>queue<span class="op">&amp;</span> q<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(...)</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Add the following paragraphs to the end of §<span>24.6.6.4
<a href="https://wg21.link/N4981#queue.mod">[queue.mod]</a></span>:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="sourceCode" id="cb15"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>value_type pop_value();</span></code></pre></div>
<p><em>Constraints</em>:
<code class="sourceCode default">c.pop_front_value()</code> is a valid
expression that is convertible to
<code class="sourceCode default">value_type</code>.</p>
<p><em>Returns</em>:
<code class="sourceCode default">c.pop_front_value()</code>.</p>
</blockquote>

</div>
<p>Modify §<span>24.6.7.1
<a href="https://wg21.link/N4981#priqueue.overview">[priqueue.overview]</a></span>p1:</p>
<blockquote>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> pop<span class="op">()</span>;</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>value_type pop_value();</ins></span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> swap<span class="op">(</span>priority_queue<span class="op">&amp;</span> q<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(...)</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Add the following paragraphs to the end of §<span>24.6.7.4
<a href="https://wg21.link/N4981#priqueue.members">[priqueue.members]</a></span>:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="sourceCode" id="cb17"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>value_type pop_value();</span></code></pre></div>
<p><em>Constraints</em>:
<code class="sourceCode default">c.pop_back_value()</code> is a valid
expression that is convertible to
<code class="sourceCode default">value_type</code>.</p>
<p><em>Effects</em>: Calls <code class="sourceCode default">pop_heap(c.begin(), c.end(), comp)</code>.</p>
<p><em>Returns</em>:
<code class="sourceCode default">c.pop_back_value()</code>.</p>
</blockquote>

</div>
<p>Modify §<span>24.6.8.2
<a href="https://wg21.link/N4981#stack.defn">[stack.defn]</a></span>p1:</p>
<blockquote>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> pop<span class="op">()</span>                          <span class="op">{</span> c<span class="op">.</span>pop_back<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>value_type pop_value();</ins></span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> swap<span class="op">(</span>stack<span class="op">&amp;</span> s<span class="op">)</span> <span class="kw">noexcept</span><span class="op">(...)</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Add the following paragraphs to the end of §<span>24.6.8.5
<a href="https://wg21.link/N4981#stack.mod">[stack.mod]</a></span>:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="sourceCode" id="cb19"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>value_type pop_value();</span></code></pre></div>
<p><em>Constraints</em>:
<code class="sourceCode default">c.pop_back_value()</code> is a valid
expression that is convertible to
<code class="sourceCode default">value_type</code>.</p>
<p><em>Returns</em>:
<code class="sourceCode default">c.pop_back_value()</code>.</p>
</blockquote>

</div>
<h1 data-number="9" id="bibliography"><span class="header-section-number">9</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-meyers00" class="csl-entry" role="doc-biblioentry">
[meyers00] Scott Meyers. 2000-02-01. How Non-Member Functions Improve
Encapsulation. <a href="https://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197"><div class="csl-block">https://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197</div></a>
</div>
<div id="ref-N4981" class="csl-entry" role="doc-biblioentry">
[N4981] Thomas Köppe. 2024-04-16. Working Draft, Programming Languages —
C++. <a href="https://wg21.link/n4981"><div class="csl-block">https://wg21.link/n4981</div></a>
</div>
<div id="ref-P0135R1" class="csl-entry" role="doc-biblioentry">
[P0135R1] Richard Smith. 2016-06-20. Wording for guaranteed copy elision
through simplified value categories. <a href="https://wg21.link/p0135r1"><div class="csl-block">https://wg21.link/p0135r1</div></a>
</div>
<div id="ref-P3182R0" class="csl-entry" role="doc-biblioentry">
[P3182R0] Brian Bi. 2024-04-16. Add pop_value methods to container
adaptors. <a href="https://wg21.link/p3182r0"><div class="csl-block">https://wg21.link/p3182r0</div></a>
</div>
<div id="ref-STL" class="csl-entry" role="doc-biblioentry">
[STL] <a href="http://web.archive.org/web/20010221200527/http://www.sgi.com/tech/stl/stack.html"><div class="csl-block">http://web.archive.org/web/20010221200527/http://www.sgi.com/tech/stl/stack.html</div></a>
</div>
</div>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>These methods also provide (weak) evidence that “pop and
return the popped value” is a useful operation. In fact, I can’t think
of any reason why, in any language other than C++, a
<code class="sourceCode cpp">pop</code> method would ever be
intentionally designed to return
<code class="sourceCode cpp"><span class="dt">void</span></code> (or its
equivalent).<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>All citations to the Standard are to working draft N4981
unless otherwise specified.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3"><p>The technique for doing so would be: suppose one wishes
to add an element to the end of the vector. If
<code class="sourceCode cpp">T</code> is nothrow-move-constructible, or
if <code class="sourceCode cpp">size<span class="op">()</span> <span class="op">&lt;</span> capacity<span class="op">()</span></code>,
then just call <code class="sourceCode cpp">push_back</code> normally.
Otherwise, create a new empty vector, reserve some multiple of the
original vector’s capacity, copy-insert the old vector’s elements into
it followed by the new element, swap the new vector with the old one,
and then destroy the new one.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4"><p>The <code class="sourceCode cpp">pop_front</code> and
<code class="sourceCode cpp">pop_back</code> methods of the Standard
Library’s sequence containers never throw an exception (§<span>24.2.2.2
<a href="https://wg21.link/N4981#container.reqmts">[container.reqmts]</a></span>p66.3).<a href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>
