<!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-04-16" />
  <title>Add `pop_value` methods to container adaptors</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
<code class="sourceCode cpp">pop_value</code> methods to container
adaptors</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3182R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-04-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="#introduction" id="toc-introduction"><span class="toc-section-number">2</span> Introduction</a></li>
<li><a href="#reasons-for-the-status-quo" id="toc-reasons-for-the-status-quo"><span class="toc-section-number">3</span> Reasons for the status quo</a>
<ul>
<li><a href="#efficiency" id="toc-efficiency"><span class="toc-section-number">3.1</span> Efficiency</a></li>
<li><a href="#exception-safety" id="toc-exception-safety"><span class="toc-section-number">3.2</span> Exception safety</a></li>
</ul></li>
<li><a href="#solution" id="toc-solution"><span class="toc-section-number">4</span> Solution</a>
<ul>
<li><a href="#stdstack-and-stdqueue" id="toc-stdstack-and-stdqueue"><span class="toc-section-number">4.1</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>
<ul>
<li><a href="#throwing-pop_back-operations" id="toc-throwing-pop_back-operations"><span class="toc-section-number">4.1.1</span> Throwing
<code class="sourceCode cpp">pop_back</code> operations</a></li>
<li><a href="#move-versus-move_if_noexcept" id="toc-move-versus-move_if_noexcept"><span class="toc-section-number">4.1.2</span>
<code class="sourceCode cpp">move</code> versus
<code class="sourceCode cpp">move_if_noexcept</code></a></li>
</ul></li>
<li><a href="#stdpriority_queue" id="toc-stdpriority_queue"><span class="toc-section-number">4.2</span> <code class="sourceCode cpp">std<span class="op">::</span>priority_queue</code></a></li>
</ul></li>
<li><a href="#alternative-names" id="toc-alternative-names"><span class="toc-section-number">5</span> Alternative names</a></li>
<li><a href="#wording" id="toc-wording"><span class="toc-section-number">6</span> Wording</a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">7</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> methods of
<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>
do not return the value popped, which is a longstanding pain point for
users of the Standard Library. I show how to implement
<code class="sourceCode cpp">pop_value</code> for
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>
and
<code class="sourceCode cpp">std<span class="op">::</span>queue</code>
so that objects are not dropped even when an exception occurs, and
propose the inclusion of these methods in the Standard Library. On the
other hand, 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="introduction"><span class="header-section-number">2</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">// invalid:</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>       <span class="co">// return d_array[d_stack.pop()];</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-11"><a href="#cb1-11" 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-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>       d_stack<span class="op">.</span>pop<span class="op">()</span>;</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a>       <span class="cf">return</span> top;</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-15"><a href="#cb1-15" 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.</p>
<h1 data-number="3" id="reasons-for-the-status-quo"><span class="header-section-number">3</span> Reasons for the status quo<a href="#reasons-for-the-status-quo" class="self-link"></a></h1>
<h2 data-number="3.1" id="efficiency"><span class="header-section-number">3.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>c<span class="op">.</span>back<span class="op">())</span>;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    c<span class="op">.</span>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/N4971#class.copy.elision">[class.copy.elision]</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</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/N4971#expr.prim.id.unqual">[expr.prim.id.unqual]</a></span>).</p>
<h2 data-number="3.2" id="exception-safety"><span class="header-section-number">3.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. 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="4" id="solution"><span class="header-section-number">4</span> Solution<a href="#solution" class="self-link"></a></h1>
<h2 data-number="4.1" id="stdstack-and-stdqueue"><span class="header-section-number">4.1</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>It is possible to implement <code class="sourceCode cpp">std<span class="op">::</span>stack<span class="op">&lt;</span>T<span class="op">&gt;::</span>pop_value</code>
and <code class="sourceCode cpp">std<span class="op">::</span>queue<span class="op">&lt;</span>T<span class="op">&gt;::</span>pop_value</code>
so that they provide the same exception safety guarantee as calling
<code class="sourceCode cpp">top</code> or
<code class="sourceCode cpp">front</code> first and then calling
<code class="sourceCode cpp">pop</code>, and, therefore, do not drop
elements when <code class="sourceCode cpp">T</code>’s move constructor
throws. The following is a proof-of-concept implementation for
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>.
The implementation for
<code class="sourceCode cpp">std<span class="op">::</span>queue</code>
is very similar.</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>        stack<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>c<span class="op">.</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>c<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_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>stack<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_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_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 the
underlying container <code class="sourceCode cpp">c</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 at the top of the stack is
popped from <code class="sourceCode cpp">c</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 the underlying container. 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_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_value</code> provides the basic
exception safety guarantee in that the stack remains in a valid state,
and additionally guarantees that the item at the top of the stack 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_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_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_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="4.1.1" id="throwing-pop_back-operations"><span class="header-section-number">4.1.1</span> Throwing
<code class="sourceCode cpp">pop_back</code> operations<a href="#throwing-pop_back-operations" class="self-link"></a></h3>
<p>The above analysis assumes that the underlying
<code class="sourceCode cpp">pop_back</code> or
<code class="sourceCode cpp">pop_front</code> method never fails by
throwing an exception. It is unusual for such an exception to even be
possible<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>, but in rare cases in which such an
exception is actually thrown, it is not possible for
<code class="sourceCode cpp">pop_value</code> to successfully return
unless the exception is swallowed, because propagating the exception
will destroy the already-constructed return object (§<span>14.3
<a href="https://wg21.link/N4971#except.ctor">[except.ctor]</a></span>p2).
Therefore, the popped value would be lost. To prevent this outcome, one
possibility is to provide the
<code class="sourceCode cpp">pop_value</code> method only when it is
known that <code class="sourceCode cpp">pop_back</code> or
<code class="sourceCode cpp">pop_front</code> will never throw an
exception; however, since these methods might not have a
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
specification, such a restriction would significantly reduce the utility
of the proposed <code class="sourceCode cpp">pop_value</code> method.
Instead, I propose to simply let the exception propagate. This rare
situation, in which the user has chosen an unusual underlying container,
is the only one in which the use of
<code class="sourceCode cpp">pop_value</code> can result in an element
being dropped. In some cases, the caller may be able to tell whether an
element was dropped, <em>i.e.</em>, when the exception thrown by
<code class="sourceCode cpp">pop_value</code> is one that cannot be
thrown by the move constructor.</p>
<p>Two possible alternatives (not currently proposed) offer the user the
ability to avoid this situation or to detect and respond to it more
reliably:</p>
<ol type="1">
<li><p>During the execution of
<code class="sourceCode cpp">pop_value</code>, <code class="sourceCode cpp">std<span class="op">::</span>terminate</code> is
called if <code class="sourceCode cpp">pop_back</code> or
<code class="sourceCode cpp">pop_front</code> exits by throwing an
exception; therefore, the calling code can assume that this never
occurs. (In the above implementation, such termination can be made to
occur automatically by removing the
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
specification on <code class="sourceCode cpp">Guard</code>’s
destructor.)</p></li>
<li><ol type="a">
<li>During the execution of
<code class="sourceCode cpp">pop_value</code>, if
<code class="sourceCode cpp">pop_back</code> or
<code class="sourceCode cpp">pop_front</code> exits by throwing an
exception, then <code class="sourceCode cpp">pop_value</code> catches
the exception and wraps it in a new exception type called <code class="sourceCode cpp">std<span class="op">::</span>pop_failed</code>
that is derived from <code class="sourceCode cpp">std<span class="op">::</span>nested_exception</code>.
By catching <code class="sourceCode cpp">std<span class="op">::</span>pop_failed</code>,
the caller can check whether the exception came from the move
constructor or from the underlying container.<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></li>
<li>Same as option (a), but the specifications of the existing
<code class="sourceCode cpp">pop</code> methods of
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>
and
<code class="sourceCode cpp">std<span class="op">::</span>queue</code>
are also changed to throw <code class="sourceCode cpp">std<span class="op">::</span>pop_failed</code>.</li>
</ol></li>
</ol>
<p>These alternatives are not currently proposed because the termination
imposed by alternative 1 may be undesirable for some users, while
alternative 2 adds complexity to the proposal without a known use
case.</p>
<h3 data-number="4.1.2" id="move-versus-move_if_noexcept"><span class="header-section-number">4.1.2</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_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_value</code> method
of
<code class="sourceCode cpp">std<span class="op">::</span>stack</code>
and
<code class="sourceCode cpp">std<span class="op">::</span>queue</code>,
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, if the value type is <code class="sourceCode cpp">std<span class="op">::</span>deque<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
with some implementations). In the case of
<code class="sourceCode cpp">pop_value</code>, I believe there are two
differences from vector reallocation that tip the balance in favor of
using
<code class="sourceCode cpp">std<span class="op">::</span>move</code>
and not <code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>:</p>
<ol type="1">
<li><code class="sourceCode cpp">pop_value</code> uses only a
<em>single</em> call to the move constructor; therefore, if
<code class="sourceCode cpp">pop_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_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), the user can fall back
on calling <code class="sourceCode cpp">top</code>, calling <code class="sourceCode cpp">std<span class="op">::</span>move_if_noexcept</code>
themselves, then calling <code class="sourceCode cpp">pop</code>. 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="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></li>
</ol>
<h2 data-number="4.2" id="stdpriority_queue"><span class="header-section-number">4.2</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="5" id="alternative-names"><span class="header-section-number">5</span> Alternative names<a href="#alternative-names" class="self-link"></a></h1>
<p>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>.</p>
<h1 data-number="6" id="wording"><span class="header-section-number">6</span> Wording<a href="#wording" class="self-link"></a></h1>
<p>The proposed wording is relative to <span class="citation" data-cites="N4971">[<a href="https://wg21.link/n4971" role="doc-biblioref">N4971</a>]</span>.</p>
<p>Modify §<span>9.4.5
<a href="https://wg21.link/N4971#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>24.6.6.1
<a href="https://wg21.link/N4971#queue.defn">[queue.defn]</a></span>p1:</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="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="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>value_type pop_value();</ins></span></span>
<span id="cb6-4"><a href="#cb6-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="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Add a new paragraph to the end of §<span>24.6.6.4
<a href="https://wg21.link/N4971#queue.mod">[queue.mod]</a></span>:</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>value_type pop_value();</span></code></pre></div>
<p><em>Effects</em>: Copy-non-list-initializes the return object from
<code class="sourceCode default">std::move(c.front())</code>, then calls
<code class="sourceCode default">c.pop_front()</code>.</p>
</blockquote>

</div>
<p>Modify §<span>24.6.7.1
<a href="https://wg21.link/N4971#priqueue.overview">[priqueue.overview]</a></span>p1:</p>
<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> pop<span class="op">()</span>;</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>value_type pop_value();</ins></span></span>
<span id="cb8-4"><a href="#cb8-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="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Add a new paragraph to the end of §<span>24.6.7.4
<a href="https://wg21.link/N4971#priqueue.members">[priqueue.members]</a></span>:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="sourceCode" id="cb9"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>value_type pop_value();</span></code></pre></div>
<p><em>Effects</em>: Calls <code class="sourceCode default">pop_heap(c.begin(), c.end(), comp)</code>,
then copy-non-list-initializes the return object from
<code class="sourceCode default">std::move(c.back())</code>, then calls
<code class="sourceCode default">c.pop_back()</code>.<br />
<em>Remarks</em>: If this function exits by throwing an exception, the
value of <code class="sourceCode default">c</code> is unspecified and is
possibly not a valid heap ([alg.heap.operations.general]).</p>
</blockquote>

</div>
<p>Modify §<span>24.6.8.2
<a href="https://wg21.link/N4971#stack.defn">[stack.defn]</a></span>p1:</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<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="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>value_type pop_value();</ins></span></span>
<span id="cb10-4"><a href="#cb10-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="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="co">// ...</span></span></code></pre></div>
</blockquote>
<p>Add a new paragraph to the end of §<span>24.6.8.5
<a href="https://wg21.link/N4971#stack.mod">[stack.mod]</a></span>:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="sourceCode" id="cb11"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>value_type pop_value();</span></code></pre></div>
<p><em>Effects</em>: Copy-non-list-initializes the return object from
<code class="sourceCode default">std::move(c.back())</code>, then calls
<code class="sourceCode default">c.pop_back()</code>.</p>
</blockquote>

</div>
<h1 data-number="7" id="bibliography"><span class="header-section-number">7</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-N4971" class="csl-entry" role="doc-biblioentry">
[N4971] Thomas Köppe. 2023-12-18. Working Draft, Programming Languages —
C++. <a href="https://wg21.link/n4971"><div class="csl-block">https://wg21.link/n4971</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-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>All citations to the Standard are to working draft N4971
unless otherwise specified.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>The <code class="sourceCode cpp">pop_front</code> and
<code class="sourceCode cpp">pop_back</code> methods of
<code class="sourceCode cpp">std<span class="op">::</span>vector</code>,
<code class="sourceCode cpp">std<span class="op">::</span>deque</code>,
and
<code class="sourceCode cpp">std<span class="op">::</span>list</code>
never throw an exception (§<span>24.2.2.2
<a href="https://wg21.link/N4971#container.reqmts">[container.reqmts]</a></span>p66.3).<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3"><p>If <code class="sourceCode cpp">value_type</code>’s move
constructor happens to propagate an exception from a failed pop
operation that it invokes, the caller needs some way to tell that the
exception thrown by <code class="sourceCode cpp">pop_value</code> came
from the move constructor and not from the direct call to
<code class="sourceCode cpp">pop_front</code> or
<code class="sourceCode cpp">pop_back</code>. Therefore, the
<code class="sourceCode cpp">pop_failed</code> exception class would
also need to hold a “depth” counter: when
<code class="sourceCode cpp">pop_value</code> catches an exception of
type <code class="sourceCode cpp">pop_failed</code> thrown by the move
constructor, it would need to increment that counter before rethrowing,
whereas a <code class="sourceCode cpp">pop_failed</code> that comes from
the direct call to <code class="sourceCode cpp">pop_front</code> or
<code class="sourceCode cpp">pop_back</code> would be initialized with a
depth of 0.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4"><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="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>
