<!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" />
  <title>An Allocator-Aware `inplace_vector`</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 { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: left;
}
@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: left; }
div.section { text-align: left; }
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">An Allocator-Aware
<code class="sourceCode cpp">inplace_vector</code></h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3160R2</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td><!-- $TimeStamp$ -->
2024-10-14 20:04 EDT<!-- $ --></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>
      Pablo Halpern<br>&lt;<a href="mailto:phalpern@halpernwightsoftware.com" class="email">phalpern@halpernwightsoftware.com</a>&gt;<br>
      Arthur O’Dwyer<br>&lt;<a href="mailto:arthur.j.odwyer@gmail.com" class="email">arthur.j.odwyer@gmail.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#abstract" id="toc-abstract"><span class="toc-section-number">1</span> Abstract<span></span></a></li>
<li><a href="#history" id="toc-history"><span class="toc-section-number">2</span> History<span></span></a></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">3</span> Motivation<span></span></a>
<ul>
<li><a href="#some-short-examples" id="toc-some-short-examples"><span class="toc-section-number">3.1</span> Some short
examples<span></span></a></li>
<li><a href="#general-motivation-for-allocator-aware-types" id="toc-general-motivation-for-allocator-aware-types"><span class="toc-section-number">3.2</span> General Motivation for
Allocator-Aware Types<span></span></a></li>
</ul></li>
<li><a href="#proposal-summary" id="toc-proposal-summary"><span class="toc-section-number">4</span> Proposal Summary<span></span></a>
<ul>
<li><a href="#adding-allocator-support-to-inplace_vector" id="toc-adding-allocator-support-to-inplace_vector"><span class="toc-section-number">4.1</span> Adding allocator support to
<code class="sourceCode cpp">inplace_vector</code><span></span></a></li>
<li><a href="#making-allocator-freestanding" id="toc-making-allocator-freestanding"><span class="toc-section-number">4.2</span> Making
<code class="sourceCode cpp">allocator</code>
Freestanding<span></span></a></li>
</ul></li>
<li><a href="#design-decisions-for-discussion" id="toc-design-decisions-for-discussion"><span class="toc-section-number">5</span> Design Decisions for
Discussion<span></span></a>
<ul>
<li><a href="#uses-allocator-construction-vs.-allocatorconstructdestroy" id="toc-uses-allocator-construction-vs.-allocatorconstructdestroy"><span class="toc-section-number">5.1</span> <em>Uses-allocator
construction</em> vs. <code class="sourceCode cpp">Allocator<span class="op">::</span>construct<span class="op">/</span>destroy</code><span></span></a></li>
<li><a href="#behavior-of-move-assignment-and-swap" id="toc-behavior-of-move-assignment-and-swap"><span class="toc-section-number">5.2</span> Behavior of move assignment and
<code class="sourceCode cpp">swap</code><span></span></a></li>
</ul></li>
<li><a href="#alternatives-considered" id="toc-alternatives-considered"><span class="toc-section-number">6</span> Alternatives
Considered<span></span></a>
<ul>
<li><a href="#using-void-instead-of-stdallocatort-for-the-default-allocator" id="toc-using-void-instead-of-stdallocatort-for-the-default-allocator"><span class="toc-section-number">6.1</span> Using
<code class="sourceCode cpp"><span class="dt">void</span></code> instead
of <code class="sourceCode cpp">std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
for the default allocator<span></span></a></li>
<li><a href="#basic_inplace_vectorclass-t-size_t-n-class-alloc-stdallocatort" id="toc-basic_inplace_vectorclass-t-size_t-n-class-alloc-stdallocatort"><span class="toc-section-number">6.2</span> <code class="sourceCode cpp">basic_inplace_vector<span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N, <span class="kw">class</span> Alloc <span class="op">=</span> std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span></code><span></span></a></li>
</ul></li>
<li><a href="#performance-and-compile-time-costs" id="toc-performance-and-compile-time-costs"><span class="toc-section-number">7</span> Performance and Compile-Time
Costs<span></span></a></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">8</span> Implementation
Experience<span></span></a></li>
<li><a href="#wording" id="toc-wording"><span class="toc-section-number">9</span> Wording<span></span></a>
<ul>
<li><a href="#feature-test-macros" id="toc-feature-test-macros"><span class="toc-section-number">9.1</span> Feature-test
macros<span></span></a></li>
<li><a href="#changes-to-stdallocator" id="toc-changes-to-stdallocator"><span class="toc-section-number">9.2</span> Changes to <code class="sourceCode cpp">std<span class="op">::</span>allocator</code><span></span></a></li>
<li><a href="#changes-to-allocator-aware-container-requirements" id="toc-changes-to-allocator-aware-container-requirements"><span class="toc-section-number">9.3</span> Changes to Allocator-aware
Container Requirements<span></span></a></li>
<li><a href="#changes-to-inplace_vector" id="toc-changes-to-inplace_vector"><span class="toc-section-number">9.4</span> Changes to
<code class="sourceCode cpp">inplace_vector</code><span></span></a>
<ul>
<li><a href="#changes-to-header-synopsis-inplace.vector.syn" id="toc-changes-to-header-synopsis-inplace.vector.syn"><span class="toc-section-number">9.4.1</span> Changes to Header Synopsis
(<span>24.3.7
<span>[inplace.vector.syn]</span></span>)<span></span></a></li>
<li><a href="#changes-to-overview-inplace.vector.overview" id="toc-changes-to-overview-inplace.vector.overview"><span class="toc-section-number">9.4.2</span> Changes to Overview
(<span>24.3.14.1
<span>[inplace.vector.overview]</span></span>)<span></span></a></li>
<li><a href="#changes-to-constructors-and-assignment-operators-inplace.vector.cons" id="toc-changes-to-constructors-and-assignment-operators-inplace.vector.cons"><span class="toc-section-number">9.4.3</span> Changes to Constructors and
Assignment Operators (<span>24.3.14.2
<span>[inplace.vector.cons]</span></span>)<span></span></a></li>
<li><a href="#changes-to-inplace_vectorswap-in-inplace.vector.modifiers" id="toc-changes-to-inplace_vectorswap-in-inplace.vector.modifiers"><span class="toc-section-number">9.4.4</span> Changes to <code class="sourceCode cpp">inplace_vector<span class="op">::</span>swap</code>
(in <span>24.3.14.5
<span>[inplace.vector.modifiers]</span></span>)<span></span></a></li>
<li><a href="#changes-to-erasure-inplace.vector.erasure" id="toc-changes-to-erasure-inplace.vector.erasure"><span class="toc-section-number">9.4.5</span> Changes to Erasure
(<span>24.3.14.6
<span>[inplace.vector.erasure]</span></span>)<span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#acknowledgments" id="toc-acknowledgments"><span class="toc-section-number">10</span>
Acknowledgments<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">11</span> References<span></span></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">inplace_vector</code> proposal,
<span class="citation" data-cites="P0843R14">[<a href="https://wg21.link/p0843r14" role="doc-biblioref">P0843R14</a>]</span>, was accepted into the working
paper without allocator support. We propose that
<code class="sourceCode cpp">inplace_vector</code> <em>should</em> have
allocator support and explores the pros and cons of adding such support
directly into <code class="sourceCode cpp">inplace_vector</code>
vs. into a separate
<code class="sourceCode cpp">basic_inplace_vector</code> class template.
In addition to providing an updated interface for
<code class="sourceCode cpp">inplace_vector</code>, this paper proposes
that <code class="sourceCode cpp">std<span class="op">::</span>allocator</code>
should be freestanding, so as allow its use as the default allocator
type, consistent with other containers.</p>
<h1 data-number="2" id="history"><span class="header-section-number">2</span> History<a href="#history" class="self-link"></a></h1>
<p><strong>New Information</strong></p>
<p>LEWG discussed this paper in March 2024 at the Tokyo WG21 meeting.
The room was roughly evenly split as to whether to pursue this paper
further. SG14 (Low-latency Study Group) discussed this paper in their
June 12, 2024 telecon to gage support for the use an allocator-aware
<code class="sourceCode cpp">inplace_vector</code> in low-latency
applications. A number of attendees voiced support for being able to
have fine-grained memory control for allocator-aware objects stored
within an <code class="sourceCode cpp">inplace_vector</code> whether or
not they would use such a facility; most of the attendees did not object
to adding allocator support to
<code class="sourceCode cpp">inplace_vector</code>, provided it did not
compromise its being freestanding. One poll was taken:</p>
<p><em>SG14 Poll: If the embeded issues can be solved, would you be OK
with adding the allocator template parameter to inplace vector?</em></p>
<table style="width:17%;">
<colgroup>
<col style="width: 4%" />
<col style="width: 2%" />
<col style="width: 2%" />
<col style="width: 2%" />
<col style="width: 4%" />
</colgroup>
<tbody>
<tr class="odd">
<td>SF</td>
<td>F</td>
<td>N</td>
<td>A</td>
<td>SA</td>
</tr>
<tr class="even">
<td>6</td>
<td>8</td>
<td>1</td>
<td>3</td>
<td>0</td>
</tr>
</tbody>
</table>
<p><strong>R2</strong></p>
<ul>
<li>In response to SG14 feedback, <code class="sourceCode cpp">std<span class="op">::</span>allocator</code> is
proposed to be freestanding so that <code class="sourceCode cpp">inplace_vector<span class="op">&lt;</span>T, allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span></code>
could be freestanding.</li>
<li>Rebased to July 2024 working paper instead of P0843, now that <span class="citation" data-cites="P0843R14">[<a href="https://wg21.link/p0843r14" role="doc-biblioref">P0843R14</a>]</span> was accepted in the June, 2024
meeting in St. Louis.</li>
<li>Removed much of the motivation, exploratory descriptions, and
alternative designs. If an allocator-aware
<code class="sourceCode cpp">inplace_vector</code> is to be part of the
standard, only one or two designs make sense. Older design discussions
can be found in the previous revisions of this paper.</li>
</ul>
<p><strong>R1</strong></p>
<ul>
<li><a href="#proposal-summary">Proposal Summary</a> section added</li>
<li><em>Design Options</em> section renamed to <a href="#alternatives-considered">Alternatives Considered</a></li>
<li><em>Compile-Time Data</em> section significantly expanded and
renamed to <a href="#performance-and-compile-time-costs">Performance and
Compile-Time Costs</a></li>
<li>Miscellaneous copy editing</li>
</ul>
<p><strong>R0</strong></p>
<ul>
<li>Initial version</li>
</ul>
<h1 data-number="3" id="motivation"><span class="header-section-number">3</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<h2 data-number="3.1" id="some-short-examples"><span class="header-section-number">3.1</span> Some short examples<a href="#some-short-examples" class="self-link"></a></h2>
<p>Consider an <code class="sourceCode cpp">inplace_vector</code>
containing at most 10 short strings:</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>std<span class="op">::</span>inplace_vector<span class="op">&lt;</span>std<span class="op">::</span>string, <span class="dv">10</span><span class="op">&gt;</span> vec;</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="st">&quot;hello&quot;</span><span class="op">)</span>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="st">&quot;bye&quot;</span><span class="op">)</span>;</span></code></pre></div>
<p>The code above would not allocate memory in most implementations
because the strings stored in the
<code class="sourceCode cpp">inplace_vector</code> fit within the
small-string optimization. This non-allocating container is a key
motivation for <code class="sourceCode cpp">inplace_vector</code>. But
what if, every once in a while, a larger string needs to be stored in
the vector?</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>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="st">&quot;A longer string that does not fit in the SSO buffer&quot;</span><span class="op">)</span>;</span></code></pre></div>
<p>To handle this possibility without accessing the heap, the programmer
switches to
<code class="sourceCode cpp">pmr<span class="op">::</span>string</code>
and sets aside a buffer that can hold the contents of larger
strings:</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><span class="dt">char</span> buffer<span class="op">[</span><span class="dv">1024</span><span class="op">]</span>;</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>pmr<span class="op">::</span>monotonic_buffer_resource mr<span class="op">(</span>buffer, <span class="dv">1034</span><span class="op">)</span>;</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>inplace_vector<span class="op">&lt;</span>std<span class="op">::</span>pmr<span class="op">::</span>string, <span class="dv">10</span><span class="op">&gt;</span> vec;</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="st">&quot;hello&quot;</span>, <span class="op">&amp;</span>mr<span class="op">)</span>;</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="st">&quot;bye&quot;</span>, <span class="op">&amp;</span>mr<span class="op">)</span>;</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>vec<span class="op">.</span>emplace_back<span class="op">(</span><span class="st">&quot;A longer string that does not fit in the SSO buffer&quot;</span>, <span class="op">&amp;</span>mr<span class="op">)</span>;</span></code></pre></div>
<p>Again, no heap accesses occur, but the code is brittle; it lacks
abstraction by exposing the allocator at every
<code class="sourceCode cpp">push_back</code> instead of relying on the
usual invariant that all elements of the vector have the same
allocator.</p>
<p>Consider what would happen if this code were in a generic function,
where <code class="sourceCode cpp">vec</code> is a template parameter.
The memory resource would not likely be available, nor could the generic
code easily determine, for a given type of
<code class="sourceCode cpp">vec</code>, whether an allocator should be
passed to <code class="sourceCode cpp">push_back</code>. For example, if
<code class="sourceCode cpp">vec</code> were created by
<code class="sourceCode cpp">make_obj_using_allocator</code>, the result
would likely not be what is expected:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>pmr::polymorphic_allocator&lt;&gt; alloc{ &amp;mr };</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>using V = std::inplace_vector&lt;std::pmr::string, 10&gt;;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>auto vec = std::make_obj_using_allocator&lt;V&gt;(alloc, { &quot;hello&quot;, &quot;bye&quot; });</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>assert(vec[0].get_allocator() == alloc);  // FAILS</span></code></pre></div>
<p>Even though an allocator is supplied, it is not used to construct the
<code class="sourceCode cpp">pmr<span class="op">::</span>string</code>
objects within the resulting
<code class="sourceCode cpp">inplace_vector</code> object because
<code class="sourceCode cpp">inplace_vector</code> does not have the
necessary hooks for
<code class="sourceCode cpp">make_obj_using_allocator</code> to
recognize it as being allocator aware. Note that, although this example
and the ones that follow use <code class="sourceCode cpp">pmr<span class="op">::</span>polymorphic_allocator</code>,
the same issues would apply to any scoped allocator.</p>
<p>A similar problem occurs if
<code class="sourceCode cpp">inplace_vector</code> is used within an
allocator-aware container:</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>std<span class="op">::</span>pmr<span class="op">::</span>vector<span class="op">&lt;</span>V<span class="op">&gt;</span> vo<span class="op">(</span>alloc<span class="op">)</span>;</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>vo<span class="op">.</span>emplace_back<span class="op">({</span> <span class="st">&quot;hello&quot;</span> <span class="op">})</span>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>vo<span class="op">.</span>back<span class="op">()[</span><span class="dv">0</span><span class="op">]-&gt;</span>get_allocator<span class="op">()</span> <span class="op">==</span> alloc<span class="op">)</span>;  <span class="co">// FAILS</span></span></code></pre></div>
<p>Again, <code class="sourceCode cpp">inplace_vector</code> lacks the
hooks needed to maintain the invariant that all parts of the outer
vector use the same allocator.</p>
<h2 data-number="3.2" id="general-motivation-for-allocator-aware-types"><span class="header-section-number">3.2</span> General Motivation for
Allocator-Aware Types<a href="#general-motivation-for-allocator-aware-types" class="self-link"></a></h2>
<p><em>Note: The text below is borrowed nearly verbatim from <span class="citation" data-cites="P3002R1">[<a href="https://wg21.link/p3002r1" role="doc-biblioref">P3002R1</a>]</span>, which proposes a general
policy for when types should use allocators.</em></p>
<p>In short, four principles underlie this policy proposal.</p>
<ol type="1">
<li><p><strong>The Standard Library should be general and
flexible</strong>. The user of a library class should have control, to
the greatest extent possible, over how memory is allocated.</p></li>
<li><p><strong>The Standard Library should be consistent</strong>. The
use of allocators should be consistent with the existing allocator-aware
classes and class templates, especially those in the containers
library.</p></li>
<li><p><strong>The parts of the Standard Library should work
together</strong>. If one part of the library gives the user control
over memory allocation but another part does not, then the second part
undermines the utility of the first.</p></li>
<li><p><strong>The Standard Library should encapsulate
complexity</strong>. The generic application of allocators with maximum
flexibility is potentially complex and is best left to the experts
implementing the Standard Library. Users can choose their own subset of
desirable allocator behavior only if the underlying Library classes
allow them to choose their preferred approach, whether it be stateless
allocators, statically typed allocators, polymorphic allocators, or no
allocators.</p></li>
</ol>
<h1 data-number="4" id="proposal-summary"><span class="header-section-number">4</span> Proposal Summary<a href="#proposal-summary" class="self-link"></a></h1>
<p>The proposal offered here includes changes to
<code class="sourceCode cpp">inplace_vector</code> (<span>24.3.14
<a href="https://wg21.link/N4986#inplace.vector">[inplace.vector]</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></span>), adding allocator
support.</p>
<p>Because <code class="sourceCode cpp">inplace_vector</code> is
intended to available in a freestanding implementation, any use of <code class="sourceCode cpp">std<span class="op">::</span>allocator</code> by
<code class="sourceCode cpp">inplace_vector</code> must also be
available in a freestanding implementation. Thus, there are changes
proposed to <code class="sourceCode cpp">allocator</code> (<span>20.2.10
<a href="https://wg21.link/N4986#default.allocator">[default.allocator]</a></span>),
making it freestanding, but see <a href="#alternatives-considered">Alternatives Considered</a> and <span class="citation" data-cites="P3295R1">[<a href="https://wg21.link/p3295r1" role="doc-biblioref">P3295R1</a>]</span> for other ways to tackle this
issue.</p>
<h2 data-number="4.1" id="adding-allocator-support-to-inplace_vector"><span class="header-section-number">4.1</span> Adding allocator support to
<code class="sourceCode cpp">inplace_vector</code><a href="#adding-allocator-support-to-inplace_vector" class="self-link"></a></h2>
<p>This paper makes <code class="sourceCode cpp">inplace_vector</code>
an <em>allocator-aware container</em> as described in <span>24.2.2.5
<a href="https://wg21.link/N4986#container.alloc.reqmts">[container.alloc.reqmts]</a></span>
and as specified below.</p>
<ul>
<li>The class template would have a third template argument,
<code class="sourceCode cpp">Allocator</code>, which would default to
<code class="sourceCode cpp">std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>.
The <code class="sourceCode cpp">std<span class="op">::</span>pmr</code>
namespace would also contain an alias:</li>
</ul>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N, <span class="kw">class</span> Allocator <span class="op">=</span> allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> inplace_vector; <span class="co">// partially freestanding</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> pmr</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> inplace_vector <span class="op">=</span> std<span class="op">::</span>inplace_vector<span class="op">&lt;</span>T, N, polymorphic_allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span>;</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<ul>
<li>The interface would add
<code class="sourceCode cpp">allocator_type</code> and
<code class="sourceCode cpp">get_allocator</code> members:</li>
</ul>
<blockquote>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> allocator_type <span class="op">=</span> Allocator;</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> allocator_type get_allocator<span class="op">()</span> <span class="kw">const</span>;</span></code></pre></div>
</blockquote>
<ul>
<li>Every constructor would have either an overload or a default
argument allowing the allocator to be passed as its last argument:</li>
</ul>
<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="kw">constexpr</span> inplace_vector<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">explicit</span> inplace_vector<span class="op">(</span><span class="kw">const</span> allocator_type<span class="op">&amp;</span> a<span class="op">)</span> <span class="kw">noexcept</span>;</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="kw">explicit</span> inplace_vector<span class="op">(</span>size_type n<span class="op">)</span>;                                      <span class="co">// <em>freestanding-deleted</em></span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> inplace_vector<span class="op">(</span>size_type n, <span class="kw">const</span> allocator_type<span class="op">&amp;</span> a<span class="op">)</span>;                      <span class="co">// <em>freestanding-deleted</em></span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> inplace_vector<span class="op">(</span>size_type n, <span class="kw">const</span> T<span class="op">&amp;</span> value, <span class="kw">const</span> allocator_type<span class="op">&amp;</span> a <span class="op">=</span> <span class="op">{})</span>; <span class="co">// <em>freestanding-deleted</em></span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="co">// etc..</span></span></code></pre></div>
</blockquote>
<ul>
<li>Elements of <code class="sourceCode cpp">inplace_vector<span class="op">&lt;</span>T, A<span class="op">&gt;</span></code>
are constructed via <em>uses-allocator construction with alloc</em>
(<span>20.2.8.2
<a href="https://wg21.link/N4986#allocator.uses.construction">[allocator.uses.construction]</a></span>),
where <code class="sourceCode cpp">alloc</code> is the return value of
<code class="sourceCode cpp">get_allocator<span class="op">()</span></code>.
This definition means that if <code class="sourceCode cpp">T</code> is
an allocator-aware type using allocator type
<code class="sourceCode cpp">A</code>, then
<code class="sourceCode cpp">alloc</code> is used to construct each
element as it is inserted into the
<code class="sourceCode cpp">inplace_vector</code>. This is not the only
possible design, however; see <a href="#design-decisions-for-discussion">Design Decisions for
Discussion</a>, below.</li>
</ul>
<h2 data-number="4.2" id="making-allocator-freestanding"><span class="header-section-number">4.2</span> Making
<code class="sourceCode cpp">allocator</code> Freestanding<a href="#making-allocator-freestanding" class="self-link"></a></h2>
<p>The <code class="sourceCode cpp">inplace_vector</code> class template
is partially freestanding. Using <code class="sourceCode cpp">allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as the default allocator for
<code class="sourceCode cpp">inplace_vector</code> presents a problem,
then, unless <code class="sourceCode cpp">allocator</code> is also
(fully or partially) freestanding. The parts of
<code class="sourceCode cpp">allocator</code> that cannot be
freestanding are the <code class="sourceCode cpp">allocate</code> and
<code class="sourceCode cpp">deallocate</code> member functions, since
they allocate memory from a runtime heap that is not guaranteed to exist
in freestanding implementations, and since
<code class="sourceCode cpp">allocate</code> may throw.</p>
<p>Fortunately, <code class="sourceCode cpp">inplace_vector</code> never
calls <code class="sourceCode cpp">allocate</code> or
<code class="sourceCode cpp">deallocate</code>, and <code class="sourceCode cpp">allocator_traits<span class="op">&lt;</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;::</span>construct</code>
and <code class="sourceCode cpp">allocator_traits<span class="op">&lt;</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;::</span>destroy</code>,
which <em>are</em> called, are <em>already</em> freestanding.
Theoretically, then, <code class="sourceCode cpp">allocator</code> could
be <em>partially freestanding</em>, with
<code class="sourceCode cpp">allocate</code> and
<code class="sourceCode cpp">deallocate</code> being
<em>freestanding-deleted</em>, but then, <code class="sourceCode cpp">std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
wouldn’t meet the requirements of an allocator anymore. Rather than
modify those requirements, we declare
<code class="sourceCode cpp">allocate</code> and
<code class="sourceCode cpp">deallocate</code> as
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
for freestanding implementations. That way, they are available for
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
applications and retain conformance with the allocator requirements, but
are not available at runtime in the freestanding environment.</p>
<p>The changes proposed here are harmonious with Ben Craig’s <span class="citation" data-cites="P3295R1">[<a href="https://wg21.link/p3295r1" role="doc-biblioref">P3295R1</a>]</span>, which proposes that a number
of standard library facilities, including the default allocator (<code class="sourceCode cpp">std<span class="op">::</span>allocator</code>) be
available in a freestanding implementation, but only in a
<code class="sourceCode cpp"><span class="kw">consteval</span></code>
context.</p>
<h1 data-number="5" id="design-decisions-for-discussion"><span class="header-section-number">5</span> Design Decisions for Discussion<a href="#design-decisions-for-discussion" class="self-link"></a></h1>
<h2 data-number="5.1" id="uses-allocator-construction-vs.-allocatorconstructdestroy"><span class="header-section-number">5.1</span> <em>Uses-allocator
construction</em> vs. <code class="sourceCode cpp">Allocator<span class="op">::</span>construct<span class="op">/</span>destroy</code><a href="#uses-allocator-construction-vs.-allocatorconstructdestroy" class="self-link"></a></h2>
<p>For wrapper types such as <code class="sourceCode cpp">tuple<span class="op">&lt;</span>T<span class="op">&gt;</span></code>,
an allocator passed to the constructor is passed through to the wrapped
<code class="sourceCode cpp">T</code> object via <em>uses-allocator
construction</em> (<span>20.2.8.2
<a href="https://wg21.link/N4986#allocator.uses.construction">[allocator.uses.construction]</a></span>),
regardless of whether the allocator is a scoped allocator. The rationale
for this design is that, since the
<code class="sourceCode cpp">tuple</code> does not itself allocate
memory, passing in an allocator that is compatible with
<code class="sourceCode cpp">T</code> but which is not passed to the
wrapped <code class="sourceCode cpp">T</code> object makes no sense. The
same logic applies to the
<code class="sourceCode cpp">basic_optional</code> and
<code class="sourceCode cpp">basic_variant</code> templates proposed in
<span class="citation" data-cites="P2047R7">[<a href="https://wg21.link/p2047r7" role="doc-biblioref">P2047R7</a>]</span> and <span class="citation" data-cites="P3153R0">[<a href="https://wg21.link/p3153r0" role="doc-biblioref">P3153R0</a>]</span>, respectively.</p>
<p>On the other hand, the requirements on an allocator-aware container
in <span>24.2.2.5
<a href="https://wg21.link/N4986#container.alloc.reqmts">[container.alloc.reqmts]</a></span>
indicate that elements should always be constructed using <code class="sourceCode cpp">allocator_traits<span class="op">&lt;</span>Allocator<span class="op">&gt;::</span>construct</code>
and destroyed using <code class="sourceCode cpp">allocator_traits<span class="op">&lt;</span>Allocator<span class="op">&gt;::</span>construct</code>.
A nonintuitive downside of following this convention for
<code class="sourceCode cpp">inplace_vector</code> is that an allocator
not having a special <code class="sourceCode cpp">construct</code>
method would effectively be ignored (but might take up space in the
object footprint). This would be the case for most non-scoped
allocators:</p>
<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="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> NonScopedAlloc</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> value_type <span class="op">=</span> T;</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>  NonScopedAlloc<span class="op">(...)</span>;</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>  value_type<span class="op">*</span> allocate<span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>;</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> deallocate<span class="op">(</span>value_type<span class="op">*</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>;</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">// `construct` and `destroy` are not declared</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyString <span class="op">=</span> std<span class="op">::</span>string<span class="op">&lt;</span><span class="dt">char</span>, std<span class="op">::</span>char_traits<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;</span>, NonScopedAlloc<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;&gt;</span>;</span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f1<span class="op">()</span></span>
<span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a>  NonScopedAlloc a<span class="op">{</span> <span class="op">...</span> <span class="op">}</span>;</span>
<span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a>  inplace_vector<span class="op">&lt;</span>MyString, NonScopedAlloc<span class="op">&lt;</span>MyString<span class="op">&gt;&gt;</span> v<span class="op">(</span>a, <span class="op">{</span> <span class="st">&quot;x&quot;</span>, <span class="st">&quot;y&quot;</span> <span class="op">})</span>;</span>
<span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a>  <span class="ot">assert</span><span class="op">(</span>v<span class="op">[</span><span class="dv">0</span><span class="op">].</span>get_allocator<span class="op">()</span> <span class="op">!=</span> a<span class="op">)</span>;  <span class="co">// Allocator `a` was not used</span></span>
<span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Despite this unintuitive behavior, the main benefits of using
<code class="sourceCode cpp">construct</code> and
<code class="sourceCode cpp">destroy</code> is that the existing wording
in <span>20.2.8.2
<a href="https://wg21.link/N4986#allocator.uses.construction">[allocator.uses.construction]</a></span>
applies unchanged, including the definitions of
<em>Cpp17DefaultInsertable</em>, <em>Cpp17MoveInsertable</em>,
<em>Cpp17CopyInsertable</em>, <em>Cpp17EmplaceConstructible</em>, and
<em>Cpp17Erasable</em>. Moreover,
<code class="sourceCode cpp">inplace_vector</code> could, in most cases,
be used as a drop-in replacement for
<code class="sourceCode cpp">vector</code>, or vice-versa, as needs
change.</p>
<p>For most scoped allocators, including <code class="sourceCode cpp">pmr<span class="op">::</span>polymorphic_allocator</code>
and <code class="sourceCode cpp">scoped_allocator_adaptor<span class="op">&lt;</span>A<span class="op">&gt;</span></code>,
the two designs are equivalent. If a scoped allocator uses different
allocation mechanisms at different nesting levels (e.g., <code class="sourceCode cpp">scoped_allocator_adaptor<span class="op">&lt;</span>A1, A2<span class="op">&gt;</span></code>),
however <em>uses-allocator construction</em> will pass
<code class="sourceCode cpp">A1</code> to
<code class="sourceCode cpp">T</code>’s constructor (ignoring
<code class="sourceCode cpp">A2</code>) whereas
<code class="sourceCode cpp">construct</code> will pass either
<code class="sourceCode cpp">A1</code> or
<code class="sourceCode cpp">A2</code> to
<code class="sourceCode cpp">T</code>, depending on the definition of
<code class="sourceCode cpp">A1<span class="op">::</span>construct</code>. It
is possible to make either design behave more-or-less like the other by
employing <code class="sourceCode cpp">scoped_allocator_adaptor<span class="op">&lt;</span>Allocator<span class="op">&gt;</span></code>.</p>
<p>The choice between these two designs also affects the behavior of
<code class="sourceCode cpp">swap</code>, as discussed next.</p>
<h2 data-number="5.2" id="behavior-of-move-assignment-and-swap"><span class="header-section-number">5.2</span> Behavior of move assignment and
<code class="sourceCode cpp">swap</code><a href="#behavior-of-move-assignment-and-swap" class="self-link"></a></h2>
<p>For all the other allocator-aware containers, move assignment and
<code class="sourceCode cpp">swap</code> do not touch the elements of
the containers; they simply change ownership of them. This behavior is
not available for <code class="sourceCode cpp">inplace_vector</code>, as
it’s not possible to transfer ownership of elements that are not on the
heap. There is a known issue with the absence of a
<code class="sourceCode cpp">swap</code> specification in
<code class="sourceCode cpp">inplace_vector</code> (see <a href="https://cplusplus.github.io/LWG/issue4151">LWG4151</a>), but there
are potentially new issues with move assignment and
<code class="sourceCode cpp">swap</code> in allocator-aware
<code class="sourceCode cpp">inplace_vector</code>.</p>
<p>For two <code class="sourceCode cpp">inplace_vector</code>s,
<code class="sourceCode cpp">a</code> and
<code class="sourceCode cpp">b</code>, A typical implementation of <code class="sourceCode cpp">a<span class="op">.</span>swap<span class="op">(</span>b<span class="op">)</span></code>
would be</p>
<ol type="1">
<li><em>Possibly</em> swap their allocators (see below).</li>
<li>Perform an element-wise swap of the first <em>n</em> elements of
<code class="sourceCode cpp">a</code> and
<code class="sourceCode cpp">b</code>, where <em>n</em> is the smaller
of <code class="sourceCode cpp">a<span class="op">.</span>size<span class="op">()</span></code>
and <code class="sourceCode cpp">b<span class="op">.</span>size<span class="op">()</span></code>.</li>
<li>Move-construct the remaining elements from the larger
<code class="sourceCode cpp">inplace_vector</code> to the smaller
one.</li>
<li>Destroy the moved-from elements.</li>
<li>Adjust the size of each container (so that their initial sizes are
swapped).</li>
</ol>
<p>For an <code class="sourceCode cpp">Allocator</code> type for which
<code class="sourceCode cpp">propagate_on_container_swap</code> (POCS)
is <code class="sourceCode cpp">false_type</code>, there are no new
issues; the allocators <em>are not swapped</em> and the precondition on
<code class="sourceCode cpp">swap</code> devolves to the preconditions
on the <code class="sourceCode cpp">T</code>’s
<code class="sourceCode cpp">swap</code> as well as the preconditions on
move construction mediated by the allocator.</p>
<p>For an <code class="sourceCode cpp">Allocator</code> type for which
POCS is <code class="sourceCode cpp">true_type</code>, the allocators
<em>are swapped</em>, so if
<code class="sourceCode cpp">a<span class="op">.</span>construct</code>
is used to construct elements of
<code class="sourceCode cpp">inplace_vector</code>,
<code class="sourceCode cpp">x</code>, then when
<code class="sourceCode cpp">a<span class="op">.</span>destroy</code> is
eventually called on those elements, the value of
<code class="sourceCode cpp">a</code> might have changed via swap (or
via an assignment, if POCMA and/or POCCA are
<code class="sourceCode cpp">true_type</code>). For the vast majority of
allocators, this apparent mismatch will make no difference, but it is
possible to create a situation where it is UB if, for example,
<code class="sourceCode cpp">construct</code> and
<code class="sourceCode cpp">destroy</code> track the address of their
arguments.</p>
<p>There are a number of design options that could resolve this
question:</p>
<ol type="1">
<li><p>Choose the <em>uses-allocator construction</em> design rather
than <code class="sourceCode cpp">Allocator<span class="op">::</span>construct<span class="op">/</span>destroy</code>
design, as described <a href="#uses-allocator-construction-vs.-allocatorconstructdestroy">above</a>
to construct new elements, thus eliminating the opportunity for a
mismatch. The simplification of the
<code class="sourceCode cpp">swap</code> specification by itself,
however, is not sufficient reason to make this design choice, as the
issue is likely to come up again in the context of
<code class="sourceCode cpp">small_vector</code> (or whatever it is
eventually called), which will almost certainly use <code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>.</p></li>
<li><p>Leave the problem to the allocator. If an allocator provides both
<code class="sourceCode cpp">construct</code> and
<code class="sourceCode cpp">destroy</code>, and if each call to the
latter must be matched up with a call to the former on the same object,
and if that allocator defines POCS to
<code class="sourceCode cpp">true_type</code>, then it is up to the
allocator author to document this fact and let users know not to
<code class="sourceCode cpp">swap</code> two
<code class="sourceCode cpp">inplace_vector</code> instances using
different values of that allocator. This is Pablo’s preferred resolution
for the <code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
design.</p></li>
<li><p>If POCS is true, make it a precondition that the allocators of
<code class="sourceCode cpp">a</code> and
<code class="sourceCode cpp">b</code> compare equal. This is Arthur’s
preferred resolution. The benefit of this approach is that it is easy to
test, within <code class="sourceCode cpp">inplace_vector</code> itself,
that the precondition holds (whereas the previous approach pushes that
concern to the allocator). The disadvantage is that POCS is often chosen
<em>specifically</em> to enable swapping containers with unequal
allocators, an intention that would be thwarted by this
resolution.</p></li>
<li><p>Add new traits and/or member functions to
<code class="sourceCode cpp">allocator_traits</code>. For example, an
<code class="sourceCode cpp">allocator_traits<span class="op">::</span>swap_elements</code>
could call an <code class="sourceCode cpp">Allocator<span class="op">::</span>swap_elements</code>
that correctly patches up the allocator’s data structure for the
mismatched <code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
pair or an <code class="sourceCode cpp">allow_mistmatched_destroy</code>
trait could be added to determine whether the equal-allocators
precondition must hold (where the trait would default to
<code class="sourceCode cpp"><span class="kw">true</span></code> if the
allocator does not provide its own
<code class="sourceCode cpp">destroy</code> member). This design space
has not been explored and is not proposed here.</p></li>
</ol>
<p>The wording in this paper uses resolution 1 for this revision.</p>
<h1 data-number="6" id="alternatives-considered"><span class="header-section-number">6</span> Alternatives Considered<a href="#alternatives-considered" class="self-link"></a></h1>
<p>Several alternative designs for an allocator-aware
<code class="sourceCode cpp">inplace_vector</code> have been considered
and discarded; see <span class="citation" data-cites="P3160R1">[<a href="https://wg21.link/p3160r1" role="doc-biblioref">P3160R1</a>]</span>. Only the ones still in play
are described here.</p>
<h2 data-number="6.1" id="using-void-instead-of-stdallocatort-for-the-default-allocator"><span class="header-section-number">6.1</span> Using
<code class="sourceCode cpp"><span class="dt">void</span></code> instead
of <code class="sourceCode cpp">std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
for the default allocator<a href="#using-void-instead-of-stdallocatort-for-the-default-allocator" class="self-link"></a></h2>
<p>This design would have two declarations:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>template &lt;class T, size_t N, class Allocator = void&gt; class inplace_vector;</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>template &lt;class T, size_t N&gt; class inplace_vector&lt;void&gt;;</span></code></pre></div>
<p>The partial specialization for the
<code class="sourceCode cpp"><span class="dt">void</span></code>
allocator would be identical (except for the extra template parameter)
to the <code class="sourceCode cpp">inplace_vector</code> currently in
the WP. It would not be an allocator-aware type; i.e., it would not have
<code class="sourceCode cpp">allocator_type</code> or <code class="sourceCode cpp">get_allocator<span class="op">()</span></code>
members. For
non-<code class="sourceCode cpp"><span class="dt">void</span></code>
allocators, the full interface described in this paper would be
available.</p>
<p><strong>Pros</strong>:</p>
<ul>
<li><p>This alternative can be added to the WP without making <code class="sourceCode cpp">std<span class="op">::</span>allocator</code> a
freestanding type.</p></li>
<li><p>The use of partial specialization would effectively force
implementers to optimize for the default (non-allocator) case.</p></li>
</ul>
<p><strong>Cons</strong></p>
<ul>
<li><p>The
<code class="sourceCode cpp"><span class="dt">void</span></code> default
is different from all other standard containers, and requires
special-case descriptions.</p></li>
<li><p>The
<code class="sourceCode cpp"><span class="dt">void</span></code>
specialization is not allocator-aware, which can be good or bad, but is,
again, different from other standard containers.</p></li>
</ul>
<h2 data-number="6.2" id="basic_inplace_vectorclass-t-size_t-n-class-alloc-stdallocatort"><span class="header-section-number">6.2</span> <code class="sourceCode cpp">basic_inplace_vector<span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N, <span class="kw">class</span> Alloc <span class="op">=</span> std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span></code><a href="#basic_inplace_vectorclass-t-size_t-n-class-alloc-stdallocatort" class="self-link"></a></h2>
<p>This approach defines a separate template,
<code class="sourceCode cpp">basic_inplace_vector</code>, that is the
same as the proposed allocator-aware
<code class="sourceCode cpp">inplace_vector</code> but without affecting
the interface of <code class="sourceCode cpp">inplace_vector</code>
currently in the WP.</p>
<p><strong>Pros</strong>:</p>
<ul>
<li><p>Reduces complexity of the non-allocator-aware
<code class="sourceCode cpp">inplace_vector</code> specification and
implementation.</p></li>
<li><p>Can be added after C++26 without breaking ABI.</p></li>
</ul>
<p><strong>Cons</strong>:</p>
<ul>
<li><p><code class="sourceCode cpp">inplace_vector</code> and
<code class="sourceCode cpp">basic_inplace_vector</code> are separate,
incompatible, types, increasing the <em>overall</em> specification and
implementation complexity of the standard library.</p></li>
<li><p>Some generic code will work with one and not the other. The user
needs to make a decision, especially in generic code, regarding whether
they ever expect to have allocator-aware elements. Choosing the shorter
name is tempting, but comes at the expense of breaking scoped allocation
in generic code.</p></li>
<li><p>This approach is inconsistent with all other standard-library
containers.</p></li>
<li><p>Has all of the flaws of <code class="sourceCode cpp">inplace_vector<span class="op">&lt;</span>T, S, <span class="dt">void</span><span class="op">&gt;</span></code>,
with none of the advantages.</p></li>
</ul>
<h1 data-number="7" id="performance-and-compile-time-costs"><span class="header-section-number">7</span> Performance and Compile-Time
Costs<a href="#performance-and-compile-time-costs" class="self-link"></a></h1>
<p>Experiments have shown that the proposed interface can be implemented
with no runtime cost and negligible compile-time costs when allocators
are not used. See <span class="citation" data-cites="P3160R1">[<a href="https://wg21.link/p3160r1" role="doc-biblioref">P3160R1</a>]</span>.</p>
<h1 data-number="8" id="implementation-experience"><span class="header-section-number">8</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>Pablo Halpern’s implementation of this proposal is available at <a href="https://github.com/phalpern/WG21-halpern/tree/P3160/P3160-AA-inplace_vector">https://github.com/phalpern/WG21-halpern/tree/main/P3160-AA-inplace_vector</a>.</p>
<p>Arthur O’Dwyer’s implementation using the <code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
design is available at <a href="https://github.com/Quuxplusone/SG14/blob/master/include/sg14/aa_inplace_vector.h">https://github.com/Quuxplusone/SG14/blob/master/include/sg14/aa_inplace_vector.h</a></p>
<p>Neither implementation includes the freestanding changes to
<code class="sourceCode cpp">allocator</code>.</p>
<h1 data-number="9" id="wording"><span class="header-section-number">9</span> Wording<a href="#wording" class="self-link"></a></h1>
<p>All wording is relative to the July 2024 working paper, <span class="citation" data-cites="N4986">[<a href="https://wg21.link/n4986" role="doc-biblioref">N4986</a>]</span>.</p>
<table>
<colgroup>
<col style="width: 100%" />
</colgroup>
<tbody>
<tr class="odd">
<td><strong><code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
Wording</strong>: The wording below assumes the <em>uses-allocator</em>
design. Wording changes needed for the <code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
design are called out in <strong><code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
Wording</strong> boxes like this one. Where the authors disagreed, both
potential wording changes are presented.</td>
</tr>
</tbody>
</table>
<h2 data-number="9.1" id="feature-test-macros"><span class="header-section-number">9.1</span> Feature-test macros<a href="#feature-test-macros" class="self-link"></a></h2>
<p>In <span>17.3.2
<a href="https://wg21.link/N4986#version.syn">[version.syn]</a></span>,
add a feature test macro for freestanding
<code class="sourceCode cpp">allocator</code>. The date, <code class="sourceCode cpp"><span class="dv">20</span><span class="er">XXXXL</span></code>,
should be replaced by the year and month that each feature was
adopted.</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="line-block"><code class="sourceCode default">#define __cpp_lib_allocator 20XXXXL                //</code>
<em>also in</em>
<code class="sourceCode default">&lt;memory&gt;</code></div>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode default">#define __cpp_lib_freestanding_allocator 20XXXXL   //</code>
<em>freestanding, also in</em>
<code class="sourceCode default">&lt;memory&gt;</code></div>
</blockquote>

</div>
<p>The first macro indicates that the entirety of the
<code class="sourceCode cpp">allocator</code> interface is supported,
whereas the second macro indicates that <em>at least</em> all of the
freestanding features are supported. In this case the minimal
freestanding features are that
<code class="sourceCode cpp">allocate</code> and
<code class="sourceCode cpp">deallocate</code> are available in a
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
context whereas the full feature set includes runtime support.</p>
<p>Also, update the version date for
<code class="sourceCode cpp">inplace_vector</code></p>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="pp">#define __cpp_lib_inplace_vector </span><span class="rm" style="color: #bf0303"><del>202406L</del></span><span class="add" style="color: #006e28"><ins>20XXXXL</ins></span><span class="pp">    </span><span class="co">//</span></code>
<em>also in</em> <code class="sourceCode cpp"><span class="op">&lt;</span>inplace_vector<span class="op">&gt;</span></code></div>
</blockquote>
<p>There is an existing issue whereby there was no feature-test macro
for the minimal freestanding subset of
<code class="sourceCode cpp">inplace_vector</code> (issue number TBD).
The following would correct this issue. Note that if the issue is
corrected prior to adopting this paper, that the date value should still
be updated:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="line-block"><code class="sourceCode default">#define __cpp_lib_freestanding_inplace_vector 20XXXXL   //</code>
<em>freestanding, also in</em>
<code class="sourceCode default">&lt;inplace_vector&gt;</code></div>
</blockquote>

</div>
<h2 data-number="9.2" id="changes-to-stdallocator"><span class="header-section-number">9.2</span> Changes to <code class="sourceCode cpp">std<span class="op">::</span>allocator</code><a href="#changes-to-stdallocator" class="self-link"></a></h2>
<p>Make the following addition to <span>20.2.2
<a href="https://wg21.link/N4986#memory.syn">[memory.syn]</a></span>.</p>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="co">//</span></code>
<em>20.2.10, the default allocator</em><br />
<code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="kw">class</span> allocator;</code>
<em><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">// partially freestanding</code></span></ins></span></em><br />
<code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="kw">class</span> U<span class="op">&gt;</span></code><br />
   <code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">==(</span><span class="kw">const</span> allocator<span class="op">&lt;</span>T<span class="op">&gt;&amp;</span>, <span class="kw">const</span> allocator<span class="op">&lt;</span>U<span class="op">&gt;&amp;)</span> <span class="kw">noexcept</span>;</code>
<em><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">// freestanding</code></span></ins></span></em></div>
</blockquote>
<p>Make the following additions to <span>20.2.10
<a href="https://wg21.link/N4986#default.allocator">[default.allocator]</a></span>.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>    namespace std {</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>      template&lt;class T&gt; class allocator {</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>      public:</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>        using value_type                             = T;</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>        using size_type                              = size_t;</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>        using difference_type                        = ptrdiff_t;</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>        using propagate_on_container_move_assignment = true_type;</span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>        constexpr allocator() noexcept;</span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>        constexpr allocator(const allocator&amp;) noexcept;</span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>        template&lt;class U&gt; constexpr allocator(const allocator&lt;U&gt;&amp;) noexcept;</span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>        constexpr ~allocator();</span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>        constexpr allocator&amp; operator=(const allocator&amp;) = default;</span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>        [[nodiscard]] constexpr T* allocate(size_t n); <span class="add" style="color: #006e28"><ins>// <em>Note 1</em></ins></span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a>        [[nodiscard]] constexpr allocation_result&lt;T*&gt; allocate_at_least(size_t n); <span class="add" style="color: #006e28"><ins>// <em>Note 1</em></ins></span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>        constexpr void deallocate(T* p, size_t n); <span class="add" style="color: #006e28"><ins>// <em>Note 1</em></ins></span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>      };</span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>    }</span></code></pre></div>
<div class="add" style="color: #006e28">

<blockquote>
<p><em>Note 1:</em> For a freestanding implementation, it is
implementation-defined whether
<code class="sourceCode default">allocate</code>,
<code class="sourceCode default">allocate_at_least</code>, and
<code class="sourceCode default">deallocate</code> are
<code class="sourceCode default">consteval</code> rather than
<code class="sourceCode default">constexpr</code>.</p>
</blockquote>

</div>
<h2 data-number="9.3" id="changes-to-allocator-aware-container-requirements"><span class="header-section-number">9.3</span> Changes to Allocator-aware
Container Requirements<a href="#changes-to-allocator-aware-container-requirements" class="self-link"></a></h2>
<p>Make the following changes to <span>24.2.2.5
<a href="https://wg21.link/N4986#container.alloc.reqmts">[container.alloc.reqmts]</a></span>.</p>
<blockquote>
<p>Except for <code class="sourceCode cpp">array</code> <span class="rm" style="color: #bf0303"><del>and
<span><code class="sourceCode default">inplace_vector</code></span></del></span>,
all of the containers defined in Clause 24, 19.6.4, 23.4.3, and 32.9
meet the additional requirements of an <em>allocator-aware
container</em>, as described below.</p>
</blockquote>
<blockquote>
<p>Given an allocator type <code class="sourceCode cpp">A</code> and
given a container type <code class="sourceCode cpp">X</code> having a
<code class="sourceCode cpp">value_type</code> identical to
<code class="sourceCode cpp">T</code> and an
<code class="sourceCode cpp">allocator_type</code> identical to <code class="sourceCode cpp">allocator_traits<span class="op">&lt;</span>A<span class="op">&gt;::</span>rebind_alloc<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
and given an lvalue <code class="sourceCode cpp">m</code> of type
<code class="sourceCode cpp">A</code>, a pointer
<code class="sourceCode cpp">p</code> of type
<code class="sourceCode cpp">T<span class="op">*</span></code>, an
expression <code class="sourceCode cpp">v</code> that denotes an lvalue
of type <code class="sourceCode cpp">T</code> or
<code class="sourceCode cpp"><span class="kw">const</span> T</code> or
an rvalue of type
<code class="sourceCode cpp"><span class="kw">const</span> T</code>, and
an rvalue <code class="sourceCode cpp">rv</code> of type
<code class="sourceCode cpp">T</code>, the following terms are defined.
<span class="add" style="color: #006e28"><ins>If
<span><code class="sourceCode default">X</code></span> is a
specialization of
<span><code class="sourceCode default">inplace_vector</code></span>, the
terms below are defined as though
<span><code class="sourceCode default">A</code></span> were <span><code class="sourceCode default">scoped_allocator_adaptor&lt;allocator&lt;T&gt;, allocator_type&gt;</code></span></ins></span>.
If <code class="sourceCode cpp">X</code> is not allocator-aware or is a
specialization of <code class="sourceCode cpp">basic_string</code>, the
terms below are defined as if <code class="sourceCode cpp">A</code> were
<code class="sourceCode cpp">allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
— no allocator object needs to be created and user specializations of
<code class="sourceCode cpp">allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
are not instantiated:</p>
</blockquote>
<table>
<colgroup>
<col style="width: 100%" />
</colgroup>
<tbody>
<tr class="odd">
<td><strong><code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
Wording</strong>: Omit the addition (“<span class="add" style="color: #006e28"><ins>If
<span><code class="sourceCode default">X</code></span> is a
specialization…</ins></span>”), above, if the <code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
design is chosen.</td>
</tr>
</tbody>
</table>
<p>In the same section (<span>24.2.2.5
<a href="https://wg21.link/N4986#container.alloc.reqmts">[container.alloc.reqmts]</a></span>),
also change <em>Note 2</em>:</p>
<blockquote>
<p>[<em>Note 2</em>: A container calls <code class="sourceCode cpp">allocator_traits<span class="op">&lt;</span>A<span class="op">&gt;::</span>construct<span class="op">(</span>m, p, args<span class="op">)</span></code>
to construct an element at <code class="sourceCode cpp">p</code> using
<code class="sourceCode cpp">args</code>, with <code class="sourceCode cpp">m <span class="op">==</span> get_allocator<span class="op">()</span></code>
<span class="add" style="color: #006e28"><ins>(or <span><code class="sourceCode default">m == A(allocator&lt;T&gt;(), get_allocator())</code></span>
in the case of
<span><code class="sourceCode default">inplace_vector</code></span>)</ins></span>.
The default <code class="sourceCode cpp">construct</code> in
<code class="sourceCode cpp">allocator</code> will call <code class="sourceCode cpp"><span class="op">::</span><span class="kw">new</span><span class="op">((</span><span class="dt">void</span><span class="op">*)</span>p<span class="op">)</span> T<span class="op">(</span>args<span class="op">)</span></code>,
but specialized allocators can choose a different definition. — <em>end
note</em>]</p>
</blockquote>
<table>
<colgroup>
<col style="width: 100%" />
</colgroup>
<tbody>
<tr class="odd">
<td><strong><code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
Wording</strong>: Omit the changes to <em>Note 2</em> if the <code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
design is chosen.</td>
</tr>
</tbody>
</table>
<p>In the same section, update the complexity clauses of move
construction and <code class="sourceCode cpp">swap</code> for
allocator-aware containers as follows:</p>
<p><code class="sourceCode cpp">X u<span class="op">(</span>rv<span class="op">)</span>;</code></p>
<blockquote>
<p><em>Postconditions</em>: <code class="sourceCode cpp">u</code> has
the same elements as <code class="sourceCode cpp">rv</code> had before
this construction; the value of <code class="sourceCode cpp">u<span class="op">.</span>get_allocator<span class="op">()</span></code>
is the same as the value of <code class="sourceCode cpp">rv<span class="op">.</span>get_allocator<span class="op">()</span></code>
before this construction.</p>
</blockquote>
<blockquote>
<p><em>Complexity</em>: <span class="rm" style="color: #bf0303"><del>Constant</del></span><span class="add" style="color: #006e28"><ins>Linear for
<span><code class="sourceCode default">inplace_vector</code></span>;
constant for all other allocator-aware standard
containers</ins></span>.</p>
</blockquote>
<p><code class="sourceCode cpp">X u<span class="op">(</span>rv, m<span class="op">)</span>;</code></p>
<blockquote>
<p><em>Preconditions</em>: <code class="sourceCode cpp">T</code> is
<em>Cpp17MoveInsertable</em> into
<code class="sourceCode cpp">X</code>.</p>
</blockquote>
<blockquote>
<p><em>Postconditions</em>: <code class="sourceCode cpp">u</code> has
the same elements, or copies of the elements, that
<code class="sourceCode cpp">rv</code> had before this construction,
<code class="sourceCode cpp">u<span class="op">.</span>get_allocator<span class="op">()</span> <span class="op">==</span> m</code>.</p>
</blockquote>
<blockquote>
<p>Complexity: <span class="rm" style="color: #bf0303"><del>Constant</del></span><span class="add" style="color: #006e28"><ins>Linear for
<span><code class="sourceCode default">inplace_vector</code></span>;</ins></span>
<span class="add" style="color: #006e28"><ins>constant for all other
allocator-aware standard containers</ins></span> if <code class="sourceCode cpp">m <span class="op">==</span> rv<span class="op">.</span>get_allocator<span class="op">()</span></code>,
otherwise linear.</p>
</blockquote>
<p><code class="sourceCode cpp">a<span class="op">.</span>swap<span class="op">(</span>b<span class="op">)</span></code></p>
<blockquote>
<p><em>Result</em>:
<code class="sourceCode cpp"><span class="dt">void</span></code></p>
</blockquote>
<blockquote>
<p><em>Effects</em>: Exchanges the contents of
<code class="sourceCode cpp">a</code> and
<code class="sourceCode cpp">b</code>.</p>
</blockquote>
<blockquote>
<p><em>Complexity</em>: <span class="rm" style="color: #bf0303"><del>Constant</del></span><span class="add" style="color: #006e28"><ins>Linear for
<span><code class="sourceCode default">inplace_vector</code></span>;
constant for all other allocator-aware standard
containers</ins></span>.</p>
</blockquote>
<h2 data-number="9.4" id="changes-to-inplace_vector"><span class="header-section-number">9.4</span> Changes to
<code class="sourceCode cpp">inplace_vector</code><a href="#changes-to-inplace_vector" class="self-link"></a></h2>
<h3 data-number="9.4.1" id="changes-to-header-synopsis-inplace.vector.syn"><span class="header-section-number">9.4.1</span> Changes to Header Synopsis
(<span>24.3.7
<a href="https://wg21.link/N4986#inplace.vector.syn">[inplace.vector.syn]</a></span>)<a href="#changes-to-header-synopsis-inplace.vector.syn" class="self-link"></a></h3>
<p>Update <span>24.3.7
<a href="https://wg21.link/N4986#inplace.vector.syn">[inplace.vector.syn]</a></span>
as follows.</p>
<p><strong>24.3.7 Header <code class="sourceCode cpp"><span class="op">&lt;</span>inplace_vector<span class="op">&gt;</span></code>
synopsis [inplace.vector.syn]</strong></p>
<table>
<colgroup>
<col style="width: 100%" />
</colgroup>
<tbody>
<tr class="odd">
<td><strong><code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
Wording</strong>: For the <code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
design, replace all instances of <em>is-nothrow-ua-constructible-v</em>
with <em>is-nothrow-allocator-constructible-v</em> (Pablo’s preference)
or <em>see below</em> (Arthur’s preference) throughout the wording. See
<a href="#changes-to-overview-inplace.vector.overview">Changes to
Overview</a>, below, for more detail on this design choice.</td>
</tr>
</tbody>
</table>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="co">// mostly freestanding</span></code><br />
<code class="sourceCode cpp"><span class="pp">#include </span><span class="im">&lt;compare&gt;</span><span class="pp">          </span><span class="co">// see 17.11.1</span></code><br />
<code class="sourceCode cpp"><span class="pp">#include </span><span class="im">&lt;initializer_list&gt;</span><span class="pp"> </span><span class="co">// see 17.10.2</span></code><br />
<br />
<code class="sourceCode cpp"><span class="kw">namespace</span> std <span class="op">{</span></code><br />
<br />
    <span class="add" style="color: #006e28"><ins><em><span><code class="sourceCode default">// exposition-only type traits</code></span></em></ins></span><br />
    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">template&lt;class T, class A, class... X&gt;</code></span></ins></span><br />
        <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">constexpr bool</code></span>
<em>is-nothrow-ua-constructible-v</em>
<span><code class="sourceCode default">=</code></span> <em>see
below</em>; <em>// exposition only</em></ins></span><br />
<br />
    <code class="sourceCode cpp"><span class="co">// 24.3.14, class template inplace_vector</span></code><br />
    <code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, class Allocator = allocator&lt;T&gt;</code></span></ins></span><code class="sourceCode cpp"><span class="op">&gt;</span></code><br />
        <code class="sourceCode cpp"><span class="kw">class</span> inplace_vector; <span class="co">//</span></code>
<em>partially freestanding</em><br />
<br />
    <code class="sourceCode cpp"><span class="co">// 24.3.14.6, erasure</span></code><br />
    <code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, class A</code></span></ins></span><code class="sourceCode cpp">, <span class="kw">class</span> U<span class="op">&gt;</span></code><br />
        <code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="kw">typename</span> inplace_vector<span class="op">&lt;</span>T, N</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, A</code></span></ins></span><code class="sourceCode cpp"><span class="op">&gt;::</span>size_type</code><br />
            <code class="sourceCode cpp">erase<span class="op">(</span>inplace_vector<span class="op">&lt;</span>T, N</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, A</code></span></ins></span><code class="sourceCode cpp"><span class="op">&gt;&amp;</span> c, <span class="kw">const</span> U<span class="op">&amp;</span> value<span class="op">)</span>;</code><br />
    <code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, class A</code></span></ins></span><code class="sourceCode cpp">, <span class="kw">class</span> Predicate<span class="op">&gt;</span></code><br />
        <code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="kw">typename</span> inplace_vector<span class="op">&lt;</span>T, N</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, A</code></span></ins></span><code class="sourceCode cpp"><span class="op">&gt;::</span>size_type</code><br />
            <code class="sourceCode cpp">erase_if<span class="op">(</span>inplace_vector<span class="op">&lt;</span>T, N</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, A</code></span></ins></span><code class="sourceCode cpp"><span class="op">&gt;&amp;</span> c, Predicate pred<span class="op">)</span>;</code></div>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="kw">namespace</span> pmr <span class="op">{</span></code><br />
    <code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N<span class="op">&gt;</span></code><br />
        <code class="sourceCode cpp"><span class="kw">using</span> inplace_vector <span class="op">=</span> std<span class="op">::</span>inplace_vector<span class="op">&lt;</span>T, N, polymorphic_allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span>;</code><br />
<code class="sourceCode cpp"><span class="op">}</span></code><br />
<code class="sourceCode cpp"><span class="op">}</span></code></div>
</blockquote>
<h3 data-number="9.4.2" id="changes-to-overview-inplace.vector.overview"><span class="header-section-number">9.4.2</span> Changes to Overview
(<span>24.3.14.1
<a href="https://wg21.link/N4986#inplace.vector.overview">[inplace.vector.overview]</a></span>)<a href="#changes-to-overview-inplace.vector.overview" class="self-link"></a></h3>
<p>Update <span>24.3.14.1
<a href="https://wg21.link/N4986#inplace.vector.overview">[inplace.vector.overview]</a></span>
as follows:</p>
<blockquote>
<p>An <code class="sourceCode cpp">inplace_vector</code> is a contiguous
container. Its capacity is fixed and its elements are stored within the
<code class="sourceCode cpp">inplace_vector</code> object itself. <span class="add" style="color: #006e28"><ins>[<em>Note</em>:
<span><code class="sourceCode default">inplace_vector</code></span> uses
its allocator only to construct and destroy allocator-aware elements; it
does not directly invoke the allocator’s
<span><code class="sourceCode default">allocate</code></span> or
<span><code class="sourceCode default">deallocate</code></span> members.
— <em>end note</em>]</ins></span></p>
</blockquote>
<blockquote>
<p>An <code class="sourceCode cpp">inplace_vector</code> meets all of
the requirements of a container (24.2.2.2), of a reversible container
(24.2.2.3), <span class="add" style="color: #006e28"><ins>of an
allocator-aware container (<span>24.2.2.5
<a href="https://wg21.link/N4986#container.alloc.reqmts">[container.alloc.reqmts]</a></span>),</ins></span>
of a contiguous container, and of a sequence container, including most
of the optional sequence container requirements (24.2.4). The exceptions
are the <code class="sourceCode cpp">push_front</code>,
<code class="sourceCode cpp">prepend_range</code>,
<code class="sourceCode cpp">pop_front</code>, and
<code class="sourceCode cpp">emplace_front</code> member functions,
which are not provided. Descriptions are provided here only for
operations on <code class="sourceCode cpp">inplace_vector</code> that
are not described in one of these tables or for operations where there
is additional semantic information.</p>
</blockquote>
<blockquote>
<p>For any <code class="sourceCode cpp">N</code> <span class="add" style="color: #006e28"><ins>and
<span><code class="sourceCode default">A</code></span></ins></span>,
<code class="sourceCode cpp">inplace_vector<span class="op">&lt;</span>T, N<span class="add" style="color: #006e28"><ins>, A</ins></span><span class="op">&gt;::</span>iterator</code>
and <code class="sourceCode cpp">inplace_vector<span class="op">&lt;</span>T, N<span class="add" style="color: #006e28"><ins>, A</ins></span><span class="op">&gt;::</span>const_iterator</code>
meet the constexpr iterator requirements.</p>
</blockquote>
<blockquote>
<p>For any <code class="sourceCode cpp">N <span class="op">&gt;</span> <span class="dv">0</span></code>,
if <code class="sourceCode cpp">is_trivial_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">false</span></code>,
then no <code class="sourceCode cpp">inplace_vector<span class="op">&lt;</span>T, N<span class="add" style="color: #006e28"><ins>, A</ins></span><span class="op">&gt;</span></code>
member functions are usable in constant expressions.</p>
</blockquote>
<blockquote>
<p>Any member function of <code class="sourceCode cpp">inplace_vector<span class="op">&lt;</span>T, N<span class="add" style="color: #006e28"><ins>, A</ins></span><span class="op">&gt;</span></code>
that would cause the size to exceed
<code class="sourceCode cpp">N</code> throws an exception of type
<code class="sourceCode cpp">bad_alloc</code>.</p>
</blockquote>
<blockquote>
<p>For the purpose of this overview, a specialization of <code class="sourceCode cpp">std<span class="op">::</span>allocator</code> is
treated as being trivial, trivially default constructible, trivially
copyable, trivially movable, and trivially destructible. [<em>Note</em>:
for implementations having non-trivial special member functions in
<code class="sourceCode cpp">allocator</code>,
<code class="sourceCode cpp">inplace_vector</code> might not store a
<code class="sourceCode cpp">allocator</code> object, but could use a
new, value-initialized object each time a
<code class="sourceCode cpp">allocator</code> object is required —
<em>end note</em>]</p>
</blockquote>
<blockquote>
<p>Let <code class="sourceCode cpp">IV</code> denote a specialization of
<code class="sourceCode cpp">inplace_vector<span class="op">&lt;</span>T, N<span class="add" style="color: #006e28"><ins>, A</ins></span><span class="op">&gt;</span></code>.
If <code class="sourceCode cpp">N</code> is zero <span class="add" style="color: #006e28"><ins>and
<span><code class="sourceCode default">is_empty_v&lt;A&gt;</code></span>
is
<span><code class="sourceCode default">true</code></span></ins></span>,
then <code class="sourceCode cpp">IV</code> is <span class="rm" style="color: #bf0303"><del>both trivial and</del></span> empty. <span class="add" style="color: #006e28"><ins>If
<span><code class="sourceCode default">N</code></span> is zero and
<span><code class="sourceCode default">is_trivial_v&lt;A&gt;</code></span>
is <span><code class="sourceCode default">true</code></span>, then
<span><code class="sourceCode default">IV</code></span> is
trivial.</ins></span> Otherwise:</p>
</blockquote>
<blockquote>
<ul>
<li>If <code class="sourceCode cpp">is_trivially_copy_constructible_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">&amp;&amp; is_trivially_copy_constructible_v&lt;A&gt;</code></span></ins></span>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
<span class="add" style="color: #006e28"><ins>and if <span><code class="sourceCode default">A::select_on_container_copy_construction</code></span>
does not exist,</ins></span> then <code class="sourceCode cpp">IV</code>
has a trivial copy constructor.</li>
<li>If <code class="sourceCode cpp">is_trivially_move_constructible_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">&amp;&amp; is_trivially_copy_constructible_v&lt;A&gt;</code></span></ins></span>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
then <code class="sourceCode cpp">IV</code> has a trivial move
constructor.</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li>If <code class="sourceCode cpp">is_trivially_destructible_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
then:</li>
</ul>
</blockquote>
<blockquote>
<blockquote>
<ul>
<li><span class="add" style="color: #006e28"><ins>If <span><code class="sourceCode default">is_trivially_destructible_v&lt;A&gt;</code></span>
is <span><code class="sourceCode default">true</code></span>,
then</ins></span> <code class="sourceCode cpp">IV</code> has a trivial
destructor.</li>
<li>If <code class="sourceCode cpp">is_trivially_copy_constructible_v<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></code>
<code class="sourceCode cpp">is_trivially_copy_assignable_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">&amp;&amp; is_trivially_copy_assignable_v&lt;A&gt; &amp;&amp;</code></span>
<span><code class="sourceCode default">(allocator_traits&lt;A&gt;::propagate_on_container_copy_assignment::value ||</code></span>
<span><code class="sourceCode default">allocator_traits&lt;A&gt;::is_always_equal::value)</code></span></ins></span>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
then <code class="sourceCode cpp">IV</code> has a trivial copy
assignment operator.</li>
<li>If <code class="sourceCode cpp">is_trivially_move_constructible_v<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></code>
<code class="sourceCode cpp">is_trivially_move_assignable_v<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">&amp;&amp; is_trivially_move_assignable_v&lt;A&gt; &amp;&amp;</code></span>
<span><code class="sourceCode default">(allocator_traits&lt;A&gt;::propagate_on_container_move_assignment::value ||</code></span>
<span><code class="sourceCode default">allocator_traits&lt;A&gt;::is_always_equal::value)</code></span></ins></span>
is <code class="sourceCode cpp"><span class="kw">true</span></code>,
then <code class="sourceCode cpp">IV</code> has a trivial move
assignment operator.</li>
</ul>
</blockquote>
</blockquote>
<div class="add" style="color: #006e28">

<blockquote>
<p>The exposition-only trait
<em>is-nothrow-ua-constructible-v</em><code class="sourceCode default">&lt;T, A, X...&gt;</code>
is <code class="sourceCode default">true</code> if <em>uses-allocator
construction</em> with allocator of type
<code class="sourceCode default">A</code> and constructor arguments of
types specified by <code class="sourceCode default">X...</code> (see
<span>20.2.8.2
<a href="https://wg21.link/N4986#allocator.uses.construction">[allocator.uses.construction]</a></span>)
is known to be a non-throwing operation. [<em>Note</em>: This trait can
be implemented by instantiating <code class="sourceCode default">is_nothrow_constructible_v&lt;T, Y...&gt;</code>,
where <code class="sourceCode default">Y...</code> is the set of
<code class="sourceCode default">tuple</code> arguments deduced by
<code class="sourceCode default">uses_allocator_construction_args</code>.
— <em>end note</em>]</p>
</blockquote>

</div>
<table>
<colgroup>
<col style="width: 100%" />
</colgroup>
<tbody>
<tr class="odd">
<td><p><strong><code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
Wording</strong> (Pablo’s preference): Replace the definition of
<em>is-nothrow-ua-constructible-v</em>, above, with the definition of
<em>is-nothrow-allocator-constructible-v</em> for the <code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
design:</p>
<div class="add" style="color: #006e28">

<blockquote>
<p>The exposition-only trait
<em>is-nothrow-allocator-constructible-v</em><code class="sourceCode default">&lt;T, A, X...&gt;</code>
is equivalent to <code class="sourceCode default">noexcept(A::construct(declval&lt;A&amp;&gt;(), declval&lt;T*&gt;(), declval&lt;X&gt;()...))</code>
if <code class="sourceCode default">A::construct</code> exists and <code class="sourceCode default">is_nothrow_constructible_v&lt;T, X...&gt;</code>
otherwise. [<em>Note</em>: if
<code class="sourceCode default">A::construct</code> does not exist, the
allocator type is used to construct objects and is thus effectively
ignored by <code class="sourceCode default">inplace_vector</code>. —
<em>end note</em>]</p>
</blockquote>

</div></td>
</tr>
<tr class="even">
<td><p><strong><code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
Wording</strong> (Arthur’s preference): Remove the definition of
<em>is-nothrow-ua-constructible-v</em>, above, entirely. Replace each
use in an exception specification with <em>see below</em>. The exception
specification will then be described per-operation for the case where
<code class="sourceCode cpp">Allocator</code> is <code class="sourceCode cpp">std<span class="op">::</span>allocator</code> and
left unspecified otherwise.</p>
<p>For the move and allocator-extended move constructors, add:</p>
<div class="add" style="color: #006e28">

<blockquote>
<p><em>Remarks</em>: If
<code class="sourceCode default">allocator_type</code> is
<code class="sourceCode default">allocator&lt;value_type&gt;</code>, the
exception specification is equivalent to <code class="sourceCode default">N == 0 || is_nothrow_move_constructible_v&lt;value_type&gt;</code>;
otherwise, the exception specification is unspecified.</p>
</blockquote>

</div>
<p>For the move-assignment operator, add:</p>
<div class="add" style="color: #006e28">

<blockquote>
<p><em>Remarks</em>: If
<code class="sourceCode default">allocator_type</code> is
<code class="sourceCode default">allocator&lt;value_type&gt;</code>, the
exception specification is equivalent to <code class="sourceCode default">N == 0 || is_nothrow_move_assignable_v&lt;value_type&gt; &amp;&amp; is_nothrow_move_constructible_v&lt;value_type&gt;</code>;
otherwise, the exception specification is unspecified.</p>
</blockquote>

</div>
<p>For the <code class="sourceCode cpp">swap</code> member function,
add:</p>
<div class="add" style="color: #006e28">

<blockquote>
<p><em>Remarks</em>: If
<code class="sourceCode default">allocator_type</code> is
<code class="sourceCode default">allocator&lt;value_type&gt;</code>, the
exception specification is equivalent to <code class="sourceCode default">N == 0 || is_nothrow_swappable_v&lt;value_type&gt; &amp;&amp; is_nothrow_move_constructible_v&lt;value_type&gt;</code>;
otherwise, the exception specification is unspecified.</p>
</blockquote>

</div></td>
</tr>
</tbody>
</table>
<p>Add an <code class="sourceCode cpp">Allocator</code> parameter to the
definition of <code class="sourceCode cpp">inplace_vector</code>.</p>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="kw">namespace</span> std <span class="op">{</span></code><br />
    <code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, class Allocator = allocator&lt;T&gt;</code></span></ins></span><code class="sourceCode cpp"><span class="op">&gt;</span></code><br />
    <code class="sourceCode cpp"><span class="kw">class</span> inplace_vector <span class="op">{</span></code><br />
    <code class="sourceCode cpp"><span class="kw">public</span><span class="op">:</span></code><br />
         <code class="sourceCode cpp"><span class="co">// types</span></code><br />
         <code class="sourceCode cpp"><span class="kw">using</span> value_type        <span class="op">=</span> T;</code><br />
         <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">using allocator_type    = Allocator;</code></span></ins></span><br />
         <code class="sourceCode cpp"><span class="kw">using</span> pointer           <span class="op">=</span> T<span class="op">*</span>;</code><br />
         <code class="sourceCode cpp"><span class="kw">using</span> const_pointer     <span class="op">=</span> <span class="kw">const</span> T<span class="op">*</span>;</code><br />
         <code class="sourceCode cpp"><span class="kw">using</span> reference         <span class="op">=</span> value_type<span class="op">&amp;</span>;</code><br />
         <code class="sourceCode cpp"><span class="kw">using</span> const_reference   <span class="op">=</span> <span class="kw">const</span> value_type<span class="op">&amp;</span>;</code><br />
         <code class="sourceCode cpp"><span class="kw">using</span> size_type         <span class="op">=</span> <span class="dt">size_t</span>;</code><br />
         <code class="sourceCode cpp"><span class="kw">using</span> difference_type   <span class="op">=</span> <span class="dt">ptrdiff_t</span>;</code></div>
</blockquote>
<table>
<colgroup>
<col style="width: 100%" />
</colgroup>
<tbody>
<tr class="odd">
<td><strong>LWG Issue</strong>: <em>unlike other allocator-aware
containers</em>, the <code class="sourceCode cpp">size_type</code>,
<code class="sourceCode cpp">difference_type</code>,
<code class="sourceCode cpp">pointer</code>, and
<code class="sourceCode cpp">const_pointer</code> types are not aliases
for the corresponding
<code class="sourceCode cpp">allocator_traits</code> types. The
<code class="sourceCode cpp">size_type</code> and
<code class="sourceCode cpp">difference_type</code> types are specified
by the standard to be types that can represent the distance between two
iterators. Not being stored in allocated memory, the integral type that
can represent the distance between elements in an
<code class="sourceCode cpp">inplace_vector</code> is unrelated to the
allocator. The meaning and intended use of
<code class="sourceCode cpp">pointer</code> and
<code class="sourceCode cpp">const_pointer</code> is not specified
anywhere in the standard, so it is not clear whether it should be
consistent with the allocator or consistent with the (raw) element
storage. The definitions above are consistent with raw element storage,
like <code class="sourceCode cpp">size_type</code> and
<code class="sourceCode cpp">difference_type</code>, and is also
consistent with the current use of
<code class="sourceCode cpp">pointer</code> as the return type for
<code class="sourceCode cpp">try_emplace_back</code> and
<code class="sourceCode cpp">try_push_back</code>. Arthur believes that
<code class="sourceCode cpp">pointer</code> should, instead be an alias
for <code class="sourceCode cpp">allocator_traits<span class="op">::</span>pointer</code>.
If LWG decides that the intended meaning of
<code class="sourceCode cpp">pointer</code> matches Arthur’s
understanding, then <code class="sourceCode cpp">try_emplace_back</code>
and <code class="sourceCode cpp">try_push_back</code> should be changed
to return <code class="sourceCode cpp">T<span class="op">*</span></code>
instead of <code class="sourceCode cpp">pointer</code>. See <a href="https://quuxplusone.github.io/blog/2024/08/23/boost-interprocess-tutorial/">Arthur’s
blog post</a> for a good treatment of when fancy pointers are useful
(though it doesn’t argue one way or another on this particular
issue).</td>
</tr>
</tbody>
</table>
<p>And add allocator-aware constructors and
<code class="sourceCode cpp">get_allocator</code>:</p>
<p><strong>Drafting Note</strong>: The use of <code class="sourceCode cpp">type_identity_t<span class="op">&lt;</span>Allocator<span class="op">&gt;</span></code>
for the allocator-extended copy and move constructors is consistent with
the other STL containers. CTAD needs it in order to handle
allocator-argument deduction from <code class="sourceCode cpp">memory_resource<span class="op">*</span></code>,
as in the case of <code class="sourceCode cpp">pmr<span class="op">::</span>inplace_vector<span class="op">&lt;</span>X ,<span class="dv">10</span><span class="op">&gt;</span> v; pmr<span class="op">::</span>unsynchronized_pool_resource mr; <span class="kw">auto</span> w <span class="op">=</span> inplace_vector<span class="op">(</span>v, <span class="op">&amp;</span>mr<span class="op">)</span></code>;</p>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="co">// 24.3.14.2, construct/copy/destroy</span></code><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">()</span> <span class="kw">noexcept</span></code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">(noexcept(Allocator()) : inplace_vector(Allocator()) {}</code></span></ins></span><code class="sourceCode cpp">;</code><br />
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">explicit constexpr inplace_vector(const Allocator&amp;) noexcept;</code></span></ins></span><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="kw">explicit</span> inplace_vector<span class="op">(</span>size_type n</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, const Allocator&amp; = Allocator()</code></span></ins></span><code class="sourceCode cpp"><span class="op">)</span>; <span class="co">//</span></code>
<em>freestanding-deleted</em><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">(</span>size_type n, <span class="kw">const</span> T<span class="op">&amp;</span> value</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, const Allocator&amp; = Allocator()</code></span></ins></span><code class="sourceCode cpp"><span class="op">)</span>; <span class="co">//</span></code>
<em>freestanding-deleted</em><br />
<code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> InputIterator<span class="op">&gt;</span></code><br />
    <code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">(</span>InputIterator first, InputIterator last</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">,</code></span></ins></span><br />
                                                    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">const Allocator&amp; = Allocator()</code></span></ins></span><code class="sourceCode cpp"><span class="op">)</span>; <span class="co">//</span></code>
<em>freestanding-deleted</em><br />
<code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><em>container-compatible-range</em><span class="op">&lt;</span>T<span class="op">&gt;</span> R<span class="op">&gt;</span></code><br />
    <code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">(</span>from_range_t, R<span class="op">&amp;&amp;</span> rg</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, const Allocator&amp; = Allocator()</code></span></ins></span><code class="sourceCode cpp"><span class="op">)</span>; <span class="co">//</span></code>
<em>freestanding-deleted</em><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">(</span><span class="kw">const</span> inplace_vector<span class="op">&amp;)</span>;</code><br />
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">constexpr inplace_vector(const inplace_vector&amp;, const type_identity_t&lt;Allocator&gt;&amp;);</code></span></ins></span><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">(</span>inplace_vector<span class="op">&amp;&amp;)</span></code><br />
    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">noexcept(N == 0 || is_nothrow_move_constructible_v&lt;T&gt;)</code></span></del></span><br />
    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">noexcept(N == 0 || <em>is-nothrow-ua-constructible-v</em>&lt;T, Allocator, T&amp;&amp;&gt;)</code></span></ins></span><code class="sourceCode cpp">;</code><br />
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">constexpr inplace_vector(inplace_vector&amp;&amp;, const type_identity_t&lt;Allocator&gt;&amp;)</code></span></ins></span><br />
    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">noexcept(N == 0 || <em>is-nothrow-ua-constructible-v</em>&lt;T, Allocator, T&amp;&amp;&gt;);</code></span></ins></span><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">(</span>initializer_list<span class="op">&lt;</span>T<span class="op">&gt;</span> il</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, const Allocator&amp; = Allocator()</code></span></ins></span><code class="sourceCode cpp"><span class="op">)</span>; <span class="co">//</span></code>
<em>freestanding-deleted</em><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="op">~</span>inplace_vector<span class="op">()</span>;</code><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="kw">const</span> inplace_vector<span class="op">&amp;</span> other<span class="op">)</span>;</code><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span>inplace_vector<span class="op">&amp;&amp;</span> other<span class="op">)</span></code><br />
    <code class="sourceCode cpp"><span class="kw">noexcept</span><span class="op">(</span>N <span class="op">==</span> <span class="dv">0</span> <span class="op">||</span> <span class="op">(</span>is_nothrow_move_assignable_v<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></code><br />
                                         <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">is_nothrow_move_constructible_v&lt;T&gt;</code></span></del></span><br />
                                         <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em>is-nothrow-ua-constructible-v</em>&lt;T, Allocator, T&amp;&amp;&gt;</code></span></ins></span><code class="sourceCode cpp"><span class="op">))</span>;</code><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span>initializer_list<span class="op">&lt;</span>T<span class="op">&gt;)</span>; <span class="co">//</span></code>
<em>freestanding-deleted</em><br />
<code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> InputIterator<span class="op">&gt;</span></code><br />
    <code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="dt">void</span> assign<span class="op">(</span>InputIterator first, InputIterator last<span class="op">)</span>; <span class="co">//</span></code>
<em>freestanding-deleted</em><br />
<code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><em>container-compatible-range</em><span class="op">&lt;</span>T<span class="op">&gt;</span> R<span class="op">&gt;</span></code><br />
    <code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="dt">void</span> assign_range<span class="op">(</span>R<span class="op">&amp;&amp;</span> rg<span class="op">)</span>; <span class="co">//</span></code>
<em>freestanding-deleted</em><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="dt">void</span> assign<span class="op">(</span>size_type n, <span class="kw">const</span> T<span class="op">&amp;</span> u<span class="op">)</span>; <span class="co">//</span></code>
<em>freestanding-deleted</em><br />
<code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="dt">void</span> assign<span class="op">(</span>initializer_list<span class="op">&lt;</span>T<span class="op">&gt;</span> il<span class="op">)</span>; <span class="co">//</span></code>
<em>freestanding-deleted</em><br />
<span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">constexpr allocator_type get_allocator() const noexcept;</code></span></ins></span></div>
</blockquote>
<p>Also update the
<code class="sourceCode cpp"><span class="kw">noexcept</span></code>
clause for the <code class="sourceCode cpp">swap</code> member
function</p>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="dt">void</span> swap<span class="op">(</span>inplace_vector<span class="op">&amp;</span> x<span class="op">)</span></code><br />
    <code class="sourceCode cpp"><span class="kw">noexcept</span><span class="op">(</span>N <span class="op">==</span> <span class="dv">0</span> <span class="op">||</span> <span class="op">(</span>is_nothrow_swappable_v<span class="op">&lt;</span>T<span class="op">&gt;</span> <span class="op">&amp;&amp;</span></code><br />
                                         <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">is_nothrow_move_constructible_v&lt;T&gt;</code></span></del></span><br />
                                         <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default"><em>is-nothrow-ua-constructible-v</em>&lt;T, Allocator, T&amp;&amp;&gt;</code></span></ins></span><code class="sourceCode cpp"><span class="op">))</span>;</code></div>
</blockquote>
<p>and the <code class="sourceCode cpp">swap</code> hidden-friend
function.</p>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="kw">friend</span> <span class="dt">void</span> swap<span class="op">(</span>inplace_vector<span class="op">&amp;</span> x, inplace_vector<span class="op">&amp;</span> y<span class="op">)</span></code><br />
    <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">noexcept(N == 0 || (is_nothrow_swappable_v&lt;T&gt; &amp;&amp;</code></span></del></span><br />
                                         <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">is_nothrow_move_constructible_v&lt;T&gt;))</code></span></del></span><br />
    <span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">noexcept(noexcept(x.swap(y)))</code></span></ins></span><br />
    <code class="sourceCode cpp"><span class="op">{</span> x<span class="op">.</span>swap<span class="op">(</span>y<span class="op">)</span>; <span class="op">}</span></code></div>
</blockquote>
<h3 data-number="9.4.3" id="changes-to-constructors-and-assignment-operators-inplace.vector.cons"><span class="header-section-number">9.4.3</span> Changes to Constructors and
Assignment Operators (<span>24.3.14.2
<a href="https://wg21.link/N4986#inplace.vector.cons">[inplace.vector.cons]</a></span>)<a href="#changes-to-constructors-and-assignment-operators-inplace.vector.cons" class="self-link"></a></h3>
<p>Update the Constructors section as follows.</p>
<p><strong>24.3.12.2 Constructors <span class="add" style="color: #006e28"><ins>and assignment operators</ins></span>
[inplace.vector.cons]</strong></p>
<p><code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="kw">explicit</span> inplace_vector<span class="op">(</span>size_type n</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, const Allocator&amp; = Allocator()</code></span></ins></span><code class="sourceCode cpp"><span class="op">)</span>;</code></p>
<blockquote>
<p><em>Preconditions</em>: <code class="sourceCode cpp">T</code> is
<em>Cpp17DefaultInsertable</em> into <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>.</p>
</blockquote>
<blockquote>
<p><em>Effects</em>: Constructs an
<code class="sourceCode cpp">inplace_vector</code> with
<code class="sourceCode cpp">n</code> default-inserted elements <span class="add" style="color: #006e28"><ins>using the specified
allocator</ins></span>.</p>
</blockquote>
<blockquote>
<p><em>Complexity</em>: Linear in
<code class="sourceCode cpp">n</code>.</p>
</blockquote>
<p><code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">(</span>size_type n, <span class="kw">const</span> T<span class="op">&amp;</span> value</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, const Allocator&amp; = Allocator()</code></span></ins></span><code class="sourceCode cpp"><span class="op">)</span>;</code></p>
<blockquote>
<p><em>Preconditions</em>: <code class="sourceCode cpp">T</code> is
<em>Cpp17CopyInsertable</em> into <code class="sourceCode cpp"><span class="op">*</span><span class="kw">this</span></code>.</p>
</blockquote>
<blockquote>
<p><em>Effects</em>: Constructs an
<code class="sourceCode cpp">inplace_vector</code> with
<code class="sourceCode cpp">n</code> copies of
<code class="sourceCode cpp">value</code> <span class="add" style="color: #006e28"><ins>using the specified
allocator</ins></span>.</p>
</blockquote>
<blockquote>
<p><em>Complexity</em>: Linear in
<code class="sourceCode cpp">n</code>.</p>
</blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> InputIterator<span class="op">&gt;</span></code><br />
    <code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">(</span>InputIterator first, InputIterator last</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, const Allocator&amp; = Allocator()</code></span></ins></span><code class="sourceCode cpp"><span class="op">)</span>;</code></div>
<blockquote>
<p><em>Effects</em>: Constructs an
<code class="sourceCode cpp">inplace_vector</code> equal to the range
[<code class="sourceCode cpp">first</code>,
<code class="sourceCode cpp">last</code>) <span class="add" style="color: #006e28"><ins>using the specified
allocator</ins></span>.</p>
</blockquote>
<blockquote>
<p><em>Complexity</em>: Linear in <code class="sourceCode cpp">distance<span class="op">(</span>first, last<span class="op">)</span></code>.</p>
</blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span>container<span class="op">-</span>compatible<span class="op">-</span>range <span class="op">&lt;</span>T<span class="op">&gt;</span> R<span class="op">&gt;</span></code><br />
    <code class="sourceCode cpp"><span class="kw">constexpr</span> inplace_vector<span class="op">(</span>from_range_t, R<span class="op">&amp;&amp;</span> rg</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, const Allocator&amp; = Allocator()</code></span></ins></span><code class="sourceCode cpp"><span class="op">)</span>;</code></div>
<blockquote>
<p><em>Effects</em>: Constructs an
<code class="sourceCode cpp">inplace_vector</code> object with the
elements of the range <code class="sourceCode cpp">rg</code> <span class="add" style="color: #006e28"><ins>using the specified
allocator</ins></span>.</p>
</blockquote>
<blockquote>
<p><em>Complexity</em>: Linear in <code class="sourceCode cpp">ranges<span class="op">::</span>distance<span class="op">(</span>rg<span class="op">)</span></code>.</p>
</blockquote>
<div class="add" style="color: #006e28">

<div class="line-block"><code class="sourceCode default">constexpr inplace_vector&amp; operator=(const inplace_vector&amp; other);</code></div>
<blockquote>
<p><em>Preconditions</em>: <code class="sourceCode default">T</code> is
<em>Cpp17CopyAssignable</em> and <em>Cpp17CopyInsertable</em> into
<code class="sourceCode default">inplace_vector</code>.</p>
</blockquote>
<blockquote>
<p><em>Postconditions</em>:
<code class="sourceCode default">*this == other</code> is
<code class="sourceCode default">true</code>.</p>
</blockquote>
<blockquote>
<p><em>Returns</em>: <code class="sourceCode default">*this</code>.</p>
</blockquote>
<blockquote>
<p><em>Complexity</em>: Linear</p>
</blockquote>
<div class="line-block"><code class="sourceCode default">constexpr inplace_vector&amp; operator=(inplace_vector&amp;&amp; other)</code><br />
    <code class="sourceCode default">noexcept(N == 0 || (is_nothrow_move_assignable_v&lt;T&gt; &amp;&amp;</code><br />
                                         <code class="sourceCode default"><em>is-nothrow-ua-constructible-v</em>&lt;T, Allocator, T&amp;&amp;&gt;));</code></div>
<blockquote>
<p><em>Preconditions</em>: <code class="sourceCode default">T</code> is
<em>Cpp17MoveAssignable</em> and <em>Cpp17MoveInsertable</em> into
<code class="sourceCode default">inplace_vector</code>.</p>
</blockquote>
<blockquote>
<p><em>Effects</em>: All existing elements of
<code class="sourceCode default">*this</code> are either move assigned
to or destroyed.</p>
</blockquote>
<blockquote>
<p><em>Returns</em>: <code class="sourceCode default">*this</code>.</p>
</blockquote>
<blockquote>
<p><em>Postconditions</em>: If
<code class="sourceCode default">*this</code> and
<code class="sourceCode default">other</code> do not refer to the same
object, <code class="sourceCode default">*this</code> is equal to the
value that <code class="sourceCode default">other</code> had before this
assignment.</p>
</blockquote>
<blockquote>
<p><em>Complexity</em>: Linear</p>
</blockquote>

</div>
<table>
<colgroup>
<col style="width: 100%" />
</colgroup>
<tbody>
<tr class="odd">
<td><strong><em>uses-allocator</em> Wording</strong>: The above
definitions for the assignment operators can be removed for the
<em>uses-allocator</em> design because they don’t add much to the
descriptions allocator-aware container requirements.</td>
</tr>
<tr class="even">
<td><p><strong><code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
Wording</strong>: This wording is for <strong>resolution 2 (Pablo’s
preference)</strong> described in the <a href="#behavior-of-move-assignment-and-swap">Behavior of move assignment
and <code class="sourceCode cpp">swap</code></a> section, above. Add
<em>Remarks</em> clauses for the assignment operators.</p>
<p>For the copy-assignment operator, add:</p>
<div class="add" style="color: #006e28">

<blockquote>
<p><em>Remarks</em>: If <code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::propagate_on_container_copy_assignment::value</code>
is <code class="sourceCode default">true</code>, then, after the
allocator is assigned, <code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::destroy</code>
might be invoked with an allocator having a different value than when
<code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::construct</code>
was invoked on a some element. This
<code class="sourceCode default">construct</code>-assign-<code class="sourceCode default">destroy</code>
sequence is well defined for all allocator types in the standard
library. [<em>Note</em>: No object is ever <em>deallocated</em> from an
allocator having a different value than that from which it was
<em>allocated</em>. — <em>end note</em>]</p>
</blockquote>

</div>
<p>For the move-assignment operator, add:</p>
<div class="add" style="color: #006e28">

<blockquote>
<p><em>Remarks</em>: If <code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::propagate_on_container_move_assignment::value</code>
is <code class="sourceCode default">true</code>, then, after the
allocator is assigned, <code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::destroy</code>
might be invoked with an allocator having a different value than when
<code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::construct</code>
was invoked on a some element. This
<code class="sourceCode default">construct</code>-assign-<code class="sourceCode default">destroy</code>
sequence is well defined for all allocator types in the standard
library. [<em>Note</em>: No object is ever <em>deallocated</em> from an
allocator having a different value than that from which it was
<em>allocated</em>. — <em>end note</em>]</p>
</blockquote>

</div>
<p><strong>Drafting note</strong>: The <em>Remarks</em> clauses, above,
as well as the one for <code class="sourceCode cpp">swap</code>, below,
are essentially the same. It might be better to centralize some or all
of the text.</p></td>
</tr>
<tr class="odd">
<td><p><strong><code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
Wording</strong>: This wording is for <strong>resolution 3 (Arthur’s
preference)</strong> described in the <a href="#behavior-of-move-assignment-and-swap">Behavior of move assignment
and <code class="sourceCode cpp">swap</code></a> section, above. Extend
the <em>Preconditions</em> clauses for the assignment operators.</p>
<p>For the copy-assignment operator, modify the <em>Preconditions</em>
as follows.</p>
<blockquote>
<p><em>Preconditions</em>: <code class="sourceCode cpp">T</code> is
<em>Cpp17CopyAssignable</em> and <em>Cpp17CopyInsertable</em> into
<code class="sourceCode cpp">inplace_vector</code>. <span class="add" style="color: #006e28"><ins>If <span><code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::propagate_on_container_copy_assignment::value</code></span>
is <span><code class="sourceCode default">true</code></span>, then
<span><code class="sourceCode default">other.get_allocator() == this-&gt;get_allocator()</code></span>
is
<span><code class="sourceCode default">true</code></span>.</ins></span></p>
</blockquote>
<p>For the move-assignment operator, modify the <em>Preconditions</em>
as follows.</p>
<blockquote>
<p><em>Preconditions</em>: <code class="sourceCode cpp">T</code> is
<em>Cpp17MoveAssignable</em> and <em>Cpp17MoveInsertable</em> into
<code class="sourceCode cpp">inplace_vector</code>. <span class="add" style="color: #006e28"><ins>If <span><code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::propagate_on_container_move_assignment::value</code></span>
is <span><code class="sourceCode default">true</code></span>, then
<span><code class="sourceCode default">other.get_allocator() == this-&gt;get_allocator()</code></span>
is
<span><code class="sourceCode default">true</code></span>.</ins></span></p>
</blockquote></td>
</tr>
</tbody>
</table>
<h3 data-number="9.4.4" id="changes-to-inplace_vectorswap-in-inplace.vector.modifiers"><span class="header-section-number">9.4.4</span> Changes to <code class="sourceCode cpp">inplace_vector<span class="op">::</span>swap</code>
(in <span>24.3.14.5
<a href="https://wg21.link/N4986#inplace.vector.modifiers">[inplace.vector.modifiers]</a></span>)<a href="#changes-to-inplace_vectorswap-in-inplace.vector.modifiers" class="self-link"></a></h3>
<p>Add the definition of <code class="sourceCode cpp">swap</code> to the
end of <span>24.3.14.5
<a href="https://wg21.link/N4986#inplace.vector.modifiers">[inplace.vector.modifiers]</a></span>.</p>
<div class="add" style="color: #006e28">

<div class="line-block"><code class="sourceCode default">constexpr void swap(inplace_vector&amp; x)</code><br />
    <code class="sourceCode default">noexcept(N == 0 || (is_nothrow_swappable_v&lt;T&gt; &amp;&amp;</code><br />
                                         <code class="sourceCode default"><em>is-nothrow-ua-constructible-v</em>&lt;T, Allocator, T&amp;&amp;&gt;));</code></div>
<blockquote>
<p><em>Preconditions</em>: Let <em>M</em> be
<code class="sourceCode default">min(size(), x.size())</code>. For each
non-negative integer <code class="sourceCode default">n</code> &lt;
<em>M</em>, <code class="sourceCode default">(*this)[n]</code> is
swappable with <code class="sourceCode default">x[n]</code>
(<span>16.4.4.3
<a href="https://wg21.link/N4986#swappable.requirements">[swappable.requirements]</a></span>).</p>
</blockquote>
<blockquote>
<p><em>Effects</em>: Exchanges the contents of
<code class="sourceCode default">*this</code> and
<code class="sourceCode default">x</code>.</p>
</blockquote>
<blockquote>
<p><em>Complexity</em>: Linear</p>
</blockquote>

</div>
<table>
<colgroup>
<col style="width: 100%" />
</colgroup>
<tbody>
<tr class="odd">
<td><p><strong><code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
Wording</strong>: This wording is for <strong>resolution 2 (Pablo’s
preference)</strong> described in the <a href="#behavior-of-move-assignment-and-swap">Behavior of move assignment
and <code class="sourceCode cpp">swap</code></a> section, above: Add the
following <em>Remarks</em> for the <code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
design.</p>
<div class="add" style="color: #006e28">

<blockquote>
<p><em>Remarks</em>: If <code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::propagate_on_container_swap::value</code>
is <code class="sourceCode default">true</code>, then, after the
allocators are swapped, <code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::destroy</code>
might be invoked with an allocator having a different value than when
<code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::construct</code>
was invoked on a some elements of both
<code class="sourceCode default">inplace_vector</code>s. This
<code class="sourceCode default">construct</code>-swap-<code class="sourceCode default">destroy</code>
sequence is well defined for all allocator types in the standard
library. [<em>Note</em>: No object is ever <em>deallocated</em> from an
allocator having a different value than that from which it was
<em>allocated</em>. — <em>end note</em>]</p>
</blockquote>

</div></td>
</tr>
<tr class="even">
<td><p><strong><code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
Wording</strong>: This wording is for <strong>resolution 3 (Arthur’s
preference)</strong> described in the <a href="#behavior-of-move-assignment-and-swap">Behavior of move assignment
and <code class="sourceCode cpp">swap</code></a> section, above: Change
the <em>Preconditions</em> for <code class="sourceCode cpp">swap</code>
for the <code class="sourceCode cpp">construct<span class="op">/</span>destroy</code>
design as follows.</p>
<blockquote>
<p><em>Preconditions</em>: Let <em>M</em> be <code class="sourceCode cpp">min<span class="op">(</span>size<span class="op">()</span>, x<span class="op">.</span>size<span class="op">())</span></code>.
For each non-negative integer <code class="sourceCode cpp">n</code> &lt;
<em>M</em>, <code class="sourceCode cpp"><span class="op">(*</span><span class="kw">this</span><span class="op">)[</span>n<span class="op">]</span></code>
is swappable with <code class="sourceCode cpp">x<span class="op">[</span>n<span class="op">]</span></code>
(<span>16.4.4.3
<a href="https://wg21.link/N4986#swappable.requirements">[swappable.requirements]</a></span>).
<span class="add" style="color: #006e28"><ins>If <span><code class="sourceCode default">allocator_traits&lt;allocator_type&gt;::propagate_on_container_swap::value</code></span>
is <span><code class="sourceCode default">true</code></span>, then
<span><code class="sourceCode default">other.get_allocator() == this-&gt;get_allocator()</code></span>
is
<span><code class="sourceCode default">true</code></span>.</ins></span></p>
</blockquote></td>
</tr>
</tbody>
</table>
<h3 data-number="9.4.5" id="changes-to-erasure-inplace.vector.erasure"><span class="header-section-number">9.4.5</span> Changes to Erasure
(<span>24.3.14.6
<a href="https://wg21.link/N4986#inplace.vector.erasure">[inplace.vector.erasure]</a></span>)<a href="#changes-to-erasure-inplace.vector.erasure" class="self-link"></a></h3>
<p>Add the allocator parameter to the
<code class="sourceCode cpp">erase</code> non-member functions in
<span>24.3.14.6
<a href="https://wg21.link/N4986#inplace.vector.erasure">[inplace.vector.erasure]</a></span>:</p>
<p><strong>24.3.14.6 Erasure [inplace.vector.erasure]</strong></p>
<div class="line-block"><code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, class A</code></span></ins></span><code class="sourceCode cpp">, <span class="kw">class</span> U <span class="op">=</span> T<span class="op">&gt;</span></code><br />
    <code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="dt">size_t</span> erase<span class="op">(</span>inplace_vector<span class="op">&lt;</span>T, N<span class="op">&gt;&amp;</span> c, <span class="kw">const</span> U<span class="op">&amp;</span> value<span class="op">)</span>;</code></div>
<blockquote>
<p><em>Effects</em>: Equivalent to:</p>
</blockquote>
<blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="kw">auto</span> it <span class="op">=</span> remove<span class="op">(</span>c<span class="op">.</span>begin<span class="op">()</span>, c<span class="op">.</span>end<span class="op">()</span>, value<span class="op">)</span>;</code><br />
<code class="sourceCode cpp"><span class="kw">auto</span> r <span class="op">=</span> distance<span class="op">(</span>it, c<span class="op">.</span>end<span class="op">())</span>;</code><br />
<code class="sourceCode cpp">c<span class="op">.</span>erase<span class="op">(</span>it, c<span class="op">.</span>end<span class="op">())</span>;</code><br />
<code class="sourceCode cpp"><span class="cf">return</span> r;</code></div>
</blockquote>
</blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> T, <span class="dt">size_t</span> N</code><span class="add" style="color: #006e28"><ins><span><code class="sourceCode default">, class A</code></span></ins></span><code class="sourceCode cpp">, <span class="kw">class</span> Predicate<span class="op">&gt;</span></code><br />
    <code class="sourceCode cpp"><span class="kw">constexpr</span> <span class="dt">size_t</span> erase_if<span class="op">(</span>inplace_vector<span class="op">&lt;</span>T, N<span class="op">&gt;&amp;</span> c, Predicate pred<span class="op">)</span>;</code></div>
<blockquote>
<p><em>Effects</em>: Equivalent to:</p>
</blockquote>
<blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode cpp"><span class="kw">auto</span> it <span class="op">=</span> remove_if<span class="op">(</span>c<span class="op">.</span>begin<span class="op">()</span>, c<span class="op">.</span>end<span class="op">()</span>, pred<span class="op">)</span>;</code><br />
<code class="sourceCode cpp"><span class="kw">auto</span> r <span class="op">=</span> distance<span class="op">(</span>it, c<span class="op">.</span>end<span class="op">())</span>;</code><br />
<code class="sourceCode cpp">c<span class="op">.</span>erase<span class="op">(</span>it, c<span class="op">.</span>end<span class="op">())</span>;</code></div>
</blockquote>
</blockquote>
<h1 data-number="10" id="acknowledgments"><span class="header-section-number">10</span> Acknowledgments<a href="#acknowledgments" class="self-link"></a></h1>
<p>The authors would like to thank each other for a congenial working
relationship whereby issues could be raised and addressed, and
disagreements presented fairly within this paper.</p>
<p>Thanks to SG14 for helping me identify the key requirements of
<code class="sourceCode cpp">inplace_vector</code> in embedded
environments.</p>
<p>Thanks to Ben Craig for his work on freestanding
<code class="sourceCode cpp">allocator</code>, which I’ve excerpted in
this paper.</p>
<h1 data-number="11" id="bibliography"><span class="header-section-number">11</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-N4986" class="csl-entry" role="doc-biblioentry">
[N4986] Thomas Köppe. 2024-07-16. Working Draft, Programming Languages —
C++. <a href="https://wg21.link/n4986"><div class="csl-block">https://wg21.link/n4986</div></a>
</div>
<div id="ref-P0843R14" class="csl-entry" role="doc-biblioentry">
[P0843R14] Gonzalo Brito Gadeschi, Timur Doumler, Nevin Liber, David
Sankel. 2024-06-26. inplace_vector. <a href="https://wg21.link/p0843r14"><div class="csl-block">https://wg21.link/p0843r14</div></a>
</div>
<div id="ref-P2047R7" class="csl-entry" role="doc-biblioentry">
[P2047R7] Nina Ranns, Pablo Halpern Ville Voutilainen. 2024-02-15. An
allocator-aware optional type. <a href="https://wg21.link/p2047r7"><div class="csl-block">https://wg21.link/p2047r7</div></a>
</div>
<div id="ref-P3002R1" class="csl-entry" role="doc-biblioentry">
[P3002R1] Pablo Halpern. 2024-02-15. Policies for Using Allocators in
New Library Classes. <a href="https://wg21.link/p3002r1"><div class="csl-block">https://wg21.link/p3002r1</div></a>
</div>
<div id="ref-P3153R0" class="csl-entry" role="doc-biblioentry">
[P3153R0] Nina Ranns, Pablo Halpern, Ville Voutilainen. 2024-02-15. An
allocator-aware variant type. <a href="https://wg21.link/p3153r0"><div class="csl-block">https://wg21.link/p3153r0</div></a>
</div>
<div id="ref-P3160R1" class="csl-entry" role="doc-biblioentry">
[P3160R1] Pablo Halpern. 2024-03-09. An allocator-aware
`inplace_vector`. <a href="https://wg21.link/p3160r1"><div class="csl-block">https://wg21.link/p3160r1</div></a>
</div>
<div id="ref-P3295R1" class="csl-entry" role="doc-biblioentry">
[P3295R1] Ben Craig. 2024-09-15. Freestanding constexpr containers and
constexpr exception types. <a href="https://wg21.link/p3295r1"><div class="csl-block">https://wg21.link/p3295r1</div></a>
</div>
</div>
<section class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>All citations to the Standard are to
working draft N4986 unless otherwise specified.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>
