<!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>Policies for Using Allocators in Library Classes</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: justify;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}

ul {
list-style-type: none;
padding-left: 2.5em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
ol {
padding-left: 2.5em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}

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

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

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

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

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Policies for Using
Allocators in Library Classes</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P3002R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td><!-- $TimeStamp$ -->
2024-02-15 13:04 EST<!-- $ --></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>
    </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="#change-log" id="toc-change-log"><span class="toc-section-number">2</span> Change Log<span></span></a></li>
<li><a href="#motivationrationale" id="toc-motivationrationale"><span class="toc-section-number">3</span>
Motivation/Rationale<span></span></a></li>
<li><a href="#prior-art-in-the-standard" id="toc-prior-art-in-the-standard"><span class="toc-section-number">4</span> Prior Art in the
Standard<span></span></a>
<ul>
<li><a href="#allocator-types" id="toc-allocator-types"><span class="toc-section-number">4.1</span> Allocator
Types<span></span></a></li>
<li><a href="#polymorphic-allocators" id="toc-polymorphic-allocators"><span class="toc-section-number">4.2</span> Polymorphic
Allocators<span></span></a></li>
<li><a href="#allocator-aware-containers" id="toc-allocator-aware-containers"><span class="toc-section-number">4.3</span> Allocator-aware
Containers<span></span></a></li>
<li><a href="#non-container-allocator-use" id="toc-non-container-allocator-use"><span class="toc-section-number">4.4</span> Non-container Allocator
Use<span></span></a></li>
</ul></li>
<li><a href="#survey-of-allocator-use-in-the-wider-c-community" id="toc-survey-of-allocator-use-in-the-wider-c-community"><span class="toc-section-number">5</span> Survey of Allocator Use in the Wider
C++ Community<span></span></a></li>
<li><a href="#summary-of-proposed-policies" id="toc-summary-of-proposed-policies"><span class="toc-section-number">6</span> Summary of Proposed
Policies<span></span></a></li>
<li><a href="#why-adopting-these-policies-would-improve-coherence-and-save-time" id="toc-why-adopting-these-policies-would-improve-coherence-and-save-time"><span class="toc-section-number">7</span> Why Adopting these Policies would
Improve Coherence and Save Time<span></span></a>
<ul>
<li><a href="#advantages" id="toc-advantages"><span class="toc-section-number">7.1</span> Advantages<span></span></a></li>
<li><a href="#disadvantages" id="toc-disadvantages"><span class="toc-section-number">7.2</span>
Disadvantages<span></span></a></li>
</ul></li>
<li><a href="#proposed-sd-9-wording" id="toc-proposed-sd-9-wording"><span class="toc-section-number">8</span>
Proposed SD-9 Wording<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">9</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>To ensure consistency and cut down on excessive debate, LEWG is in
the process of creating a standing document, SD-9, of design policies to
be followed by default when proposing new facilities for the Standard
Library; exceptions to these policies would require a paper author to
provide rationale for each exception. Because the Standard Library
should give users control over the source of memory used by Library
objects, policies on when and how classes should accept an allocator are
badly needed so that allocator support does not become an afterthought
or a topic of endless debate. This paper proposes a set of such
policies.</p>
<h1 data-number="2" id="change-log"><span class="header-section-number">2</span> Change Log<a href="#change-log" class="self-link"></a></h1>
<p>R1: Reorganized and added additional motivation and information
required to meet the policy-paper requirements specified in <span class="citation" data-cites="P2267R1">[<a href="#ref-P2267R1" role="doc-biblioref">P2267R1</a>]</span>.</p>
<p>R0: Initial version.</p>
<h1 data-number="3" id="motivationrationale"><span class="header-section-number">3</span> Motivation/Rationale<a href="#motivationrationale" class="self-link"></a></h1>
<p>Memory management is a major part of building software. Numerous
facilities in the C++ Standard library exist to give the programmer
maximum control over how their program uses memory:</p>
<ul>
<li><p><code class="sourceCode default">std::unique_ptr</code> and
<code class="sourceCode default">std::shared_ptr</code> are
parameterized with <em>deleter</em> objects that control, among other
things, how memory resources are reclaimed.</p></li>
<li><p><code class="sourceCode default">std::vector</code> is preferred
over other containers in many cases because its use of contiguous memory
provides optimal cache locality and minimizes allocate/deallocate
operations. Indeed, the LEWG has spent a lot of time on
<code class="sourceCode default">flat_set</code> (<span class="citation" data-cites="P1222R0">[<a href="#ref-P1222R0" role="doc-biblioref">P1222R0</a>]</span>) and
<code class="sourceCode default">flat_map</code> (<span class="citation" data-cites="P0429R3">[<a href="#ref-P0429R3" role="doc-biblioref">P0429R3</a>]</span>), whose underlying structure
defaults to <code class="sourceCode default">vector</code> for this
reason.</p></li>
<li><p>Operators <code class="sourceCode default">new</code> and
<code class="sourceCode default">delete</code> are replaceable, giving
programmers global control over how memory is allocated.</p></li>
<li><p>The C++ object model makes a clear distinction between an
object’s memory footprint and it’s lifetime.</p></li>
<li><p>Language constructs such as
<code class="sourceCode default">void*</code> and
<code class="sourceCode default">reinterpet_cast</code> provide
fine-grained access to objects’ underlying memory.</p></li>
<li><p>Standard containers and strings are parameterized with
allocators, providing object-level control over memory allocation and
element construction.</p></li>
</ul>
<p>This fine-grained control over memory that C++ gives the programmer
is a large part of why C++ is applicable to so many domains — from
embedded systems with limited memory budgets to games, high-frequency
trading, and scientific simulations that require cache locality, thread
affinity, and other memory-related performance optimizations.</p>
<p>An in-depth description of the value proposition for allocator-aware
software can be found in <span class="citation" data-cites="P2035R0">[<a href="#ref-P2035R0" role="doc-biblioref">P2035R0</a>]</span>. Standard
containers are the most ubiquitous examples of <em>allocator-aware</em>
types. Their <code class="sourceCode default">allocator_type</code> and
<code class="sourceCode default">get_allocator</code> members and
allocator-parameterized constructors allow them to be used like Lego®
parts that can be combined and nested as necessary while retaining full
programmer control over how the whole assembly allocates memory. For
scoped allocators in particular (see <a href="#Prior%20Art%20in%20the%20Standard">Prior Art</a>, below), having
each element of a container support a predictable allocator-aware
interface is crucial to giving the programmer the ability to allocate
all memory from a single memory resource, such as an arena or pool. Note
that the allocator is a <em>configuration</em> parameter of an object
and does not contribute to its value.</p>
<p>In short, the principles underlying this policy proposal are:</p>
<ol type="1">
<li><p><strong>The Standard Library should be general and
flexible</strong>. To the extent possible, the user of a library class
should have control 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>. Fully general application of allocators 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>
<li><p><strong>The Standard Library should try to provide
simplifications of complex facilities</strong>. The PMR part of the
standard library provides a simplified allocator model for a common use
case – that of providing an allocator to a class object and its subparts
without infecting the object’s type.</p></li>
</ol>
<h1 data-number="4" id="prior-art-in-the-standard"><span class="header-section-number">4</span> Prior Art in the Standard<a href="#prior-art-in-the-standard" class="self-link"></a></h1>
<h2 data-number="4.1" id="allocator-types"><span class="header-section-number">4.1</span> Allocator Types<a href="#allocator-types" class="self-link"></a></h2>
<p>An allocator type is a class template having member functions
<code class="sourceCode default">allocate</code> and
<code class="sourceCode default">deallocate</code> and, optionally,
<code class="sourceCode default">construct</code> and
<code class="sourceCode default">destroy</code>. The requirements for
allocator types are described in <span>16.4.4.6
<a href="https://wg21.link/N4971#allocator.requirements">[allocator.requirements]</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></span>.</p>
<p>Allocators can be divided into <em>stateless</em> and
<em>stateful</em> categories, with stateful allocators subdivided into
<em>shallow</em> and <em>scoped</em> subcategories. A shallow allocator
controls affects only the top-level object to which it is passed whereas
a scoped allocator affects all of its allocator-aware sub-objects as
well. The Standard Library defines two allocators,
<code class="sourceCode default">std::allocator</code>, which is
stateless, and
<code class="sourceCode default">std::pmr::polymorphic_allocator</code>,
which is scoped. It also defines
<code class="sourceCode default">std::scoped_allocator_adaptor</code>,
which makes shallow allocators into scoped allocators.</p>
<p>The <code class="sourceCode default">allocator_traits</code> class
template provides a uniform interface for all allocator types, providing
default operations and types for optional interface elements (see
<span>20.2.9
<a href="https://wg21.link/N4971#allocator.traits">[allocator.traits]</a></span>).</p>
<h2 data-number="4.2" id="polymorphic-allocators"><span class="header-section-number">4.2</span> Polymorphic Allocators<a href="#polymorphic-allocators" class="self-link"></a></h2>
<p>Classic allocators are provided as template parameters, with behavior
determined at compile time. This model does not always scale, as clients
of an allocator-aware type also need to be templates to take advantage
of the flexibility afforded by the allocator facility.</p>
<p>The
<code class="sourceCode default">std::pmr::polymorphic_allocator</code>
class template is a scoped allocator that acts as a bridge between the
traditional statically selected allocator model and a runtime-selected
allocator model. The mechanism by which a
<code class="sourceCode default">polymorphic_allocator</code> manages
memory is delegated to a <em>resource</em> object whose type is derived
from <code class="sourceCode default">std::pmr::memory_resource</code>.
Two container objects using
<code class="sourceCode default">polymorphic_allocator</code> can have
identical type yet allocate memory using different mechanisms. Moreover,
a user-defined type can use allocators in its interface and
implementation without being converted to a template, with all the
complexity and scaling issues that entails. At the cost of virtual
function dispatches for allocation and deallocation, polymorphic
allocators provide a simpler model for many uses. See my CppCon 2017
talk, <span class="citation" data-cites="Halpern2017">[<a href="#ref-Halpern2017" role="doc-biblioref">Halpern2017</a>]</span>,
for more information about polymorphic allocators and how they simplify
allocator-aware development.</p>
<h2 data-number="4.3" id="allocator-aware-containers"><span class="header-section-number">4.3</span> Allocator-aware Containers<a href="#allocator-aware-containers" class="self-link"></a></h2>
<p>Except for <code class="sourceCode default">array</code>, each
container in the Standard Library supports an allocator template
parameter and each of its constructors has a version that allows an
allocator to be passed in at initialization. An allocator-aware
container has an <code class="sourceCode default">allocator_type</code>
member type and a <code class="sourceCode default">get_allocator</code>
member function that returns the allocator. The
<code class="sourceCode default">Allocator</code> parameter for all
allocator-aware containers in the
<code class="sourceCode default">std</code> namespace defaults to
<code class="sourceCode default">std::allocator</code>.</p>
<p>Allocator-aware containers are required, per <span>24.2.2.5
<a href="https://wg21.link/N4971#container.alloc.reqmts">[container.alloc.reqmts]</a></span>,
to allocate memory and construct elements using the
<code class="sourceCode default">allocate</code> and
<code class="sourceCode default">construct</code> members of
<code class="sourceCode default">allocator_traits</code>. Whether a
container’s allocator is copied during copy construction, copy
assignment, move assignment, or swap is determined by the allocator’s
<em>propagation traits</em>, which are also accessed via
<code class="sourceCode default">allocator_traits</code>.</p>
<p>Each allocator-aware container also has an alias in the
<code class="sourceCode default">std::pmr</code> namespace for which the
<code class="sourceCode default">allocator_type</code> is
<code class="sourceCode default">std::pmr::polymorphic_allocator</code>:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> pmr <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2" 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="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">class</span> vector <span class="op">=</span> std<span class="op">::</span>vector<span class="op">&lt;</span>T, polymorphic_allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>The <code class="sourceCode default">pmr</code> alias makes the
polymorphic allocators sub-model more accessible by defining a set of
containers having the same scoped allocator type that can be nested
arbitrarily, i.e,</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>std<span class="op">::</span>pmr<span class="op">::</span>monotonic_buffer_resource buff_rsrc;</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="co">// The list and all strings within it will allocate memory from buff_rsrc.</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>pmr<span class="op">::</span>list<span class="op">&lt;</span>std<span class="op">::</span>pmr<span class="op">::</span>string<span class="op">&gt;</span> my_list<span class="op">(&amp;</span>buff_rsrc<span class="op">)</span>;</span></code></pre></div>
<h2 data-number="4.4" id="non-container-allocator-use"><span class="header-section-number">4.4</span> Non-container Allocator Use<a href="#non-container-allocator-use" class="self-link"></a></h2>
<p>Allocators are used by <code class="sourceCode default">tuple</code>,
<code class="sourceCode default">ranges::generator</code>, and
<code class="sourceCode default">string_stream</code>,
<code class="sourceCode default">sync_stream</code>, regular
expressions, and <code class="sourceCode default">promise</code>.
<code class="sourceCode default">tuple</code> is an interesting case
because it does not allocate memory directly. Rather,
<code class="sourceCode default">tuple</code>, might contain elements
that use allocators and has constructors that allow an allocator to be
forwarded to those elements. For example, <code class="sourceCode default">tuple&lt;pmr::string, int, double&gt;</code>
can be constructed with an allocator that is passed to the first
element. When an allocator is passed to a
<code class="sourceCode default">tuple</code> constructor, each element
is constructed by <em>uses-allocator construction</em> (<span>20.2.8.2
<a href="https://wg21.link/N4971#allocator.uses.construction">[allocator.uses.construction]</a></span>).
Within the definition of <em>uses-allocator construction</em>, there is
a special case for <code class="sourceCode default">std::pair</code>
that allows an allocator to be passed to the pair’s elements, even
though <code class="sourceCode default">pair</code> is not otherwise
allocator-enabled.</p>
<h1 data-number="5" id="survey-of-allocator-use-in-the-wider-c-community"><span class="header-section-number">5</span> Survey of Allocator Use in the
Wider C++ Community<a href="#survey-of-allocator-use-in-the-wider-c-community" class="self-link"></a></h1>
<p>C++ allocators are used for a variety of purposes in various
industries. Although statistics are hard to come by, below are some
industry anecdotes.</p>
<ul>
<li><strong>Bloomberg (financial services)</strong>: Bloomberg is
probably the biggest proponent of allocator use in the community. Most
of Bloomberg’s C++ code base is allocator-enabled and allocators are
used for a variety of purposes: cache locality, thread affinity, thread
safety, shared memory, bug detection, and a type of garbage collection
called <em>winking out</em>. Winking out is the act of abandoning an
object without invoking its destructor and reclaiming all memory
allocated by that object and its subobjects in a single operation.
Though the informative paper <span class="citation" data-cites="P2127R0">[<a href="#ref-P2127R0" role="doc-biblioref">P2127R0</a>]</span><a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> was
originally a tutorial for Bloomberg engineers, the general concepts in
its first few sections of can be useful for WG21 members interested in
how allocator-aware software is put together.</li>
</ul>
<ul>
<li><p><strong>Intel (enabling software for Intel microchips)</strong>:
Intel uses allocators to provide thread safety and thread affinity, as
well as to allocate specific data structures in special-purpose memory
pools such as high-bandwidth memory and accelerator memory.</p></li>
<li><p><strong>Cradle (music production software)</strong>: Cradle used
allocators to provide deterministic execution time for allocating from a
fixed buffer. They use
<code class="sourceCode default">pmr::polymorphic_allocator</code> with
<code class="sourceCode default">pmr::monotonic_buffer_resource</code>
and <code class="sourceCode default">std::pmr::unsynchronized_pool_resource</code>
chained together to achieve determimism with ease of use.</p></li>
<li><p><strong>Nvidia (GPUs)</strong>: Nvidia uses allocators both for
GPU memory and for local memory on CPUs. They use a custom approach
similar to <code class="sourceCode default">pmr</code> that lets
allocation be asynchronous with respect to a stream (“stream-ordered”).
Mark Hoemmen said “The best part of this model is that users can control
allocation behavior, without needing to think too much about
it.”</p></li>
<li><p><strong>NI (computerized lab instrumentation)</strong>: NI used
an allocator in their kernel-mode drivers to provide page-locked memory,
and another allocator that provides pageable memory. Their use was not
entirely standards conforming.</p></li>
<li><p><strong>Multiple companies (Cyclic Graph)</strong>: Graphs with
cycles create notoriously difficult memory-management problems. Using
<code class="sourceCode default">shared_ptr</code> alone creates cycles
that never get deallocated whereas using
<code class="sourceCode default">weak_ptr</code> requires a separate
registry to refer to all nodes. The entire graph can be managed,
however, by allocating all of the nodes from a common pool- or arena-
allocator, which reclaims all used memory at once when the graph is no
longer needed. Note that this approach assumes that no resources besides
memory are held by the nodes (because node destructors are not called).
This approach implements a modest part of the design described by Herb
Sutter in his CppCon 2016 keynote, <span class="citation" data-cites="Sutter2016">[<a href="#ref-Sutter2016" role="doc-biblioref">Sutter2016</a>]</span>.</p></li>
</ul>
<h1 data-number="6" id="summary-of-proposed-policies"><span class="header-section-number">6</span> Summary of Proposed Policies<a href="#summary-of-proposed-policies" class="self-link"></a></h1>
<p>The policies described in the <a href="#Proposed%20SD-9%20Wording">Proposed SD-9 Wording</a> section,
below, are intended to ensure that new classes that allocate memory,
directly or indirectly, are designed to enable the use of allocators to
preform that allocation. It would be ideal if some or all of the
<em>allocator-aware containers</em> requirements described in
<span>24.2.2.5
<a href="https://wg21.link/N4971#container.alloc.reqmts">[container.alloc.reqmts]</a></span>
were hoisted to their own section of the standard, describing all
allocator-aware classes, not just containers. Such a change to the
standard is outside the scope of this policy proposal, but is worth
considering for the future, as it would make wording of these policies a
bit simpler.</p>
<p>The most salient policy proposals are that:</p>
<ul>
<li><p>A class that might allocate per-object memory should be allocator
aware.</p></li>
<li><p>A class that contains members that might allocate per-object
memory should accept an allocator on construction and forward it to
those members’ constructors.</p></li>
</ul>
<p>An exception is made for situations where the overhead caused by an
allocator parameter would be too great. Specifically, if the
compile-time or runtime overhead of using <code class="sourceCode default">X&lt;T, Alloc = std::allocator&lt;&gt;&gt;</code>
is excessive, then it might make sense to define non-allocator-aware
class <code class="sourceCode default">X&lt;T&gt;</code> and a separate
allocator-aware
<code class="sourceCode default">basic_X&lt;T, Alloc&gt;</code> class.
This approach is not encouraged, however, as it can lead to
interoperability problems and presents a confusing choice to the
programmer. Note that, as with all policy exceptions, it is incumbent on
the author of a library proposal to justify its application.</p>
<h1 data-number="7" id="why-adopting-these-policies-would-improve-coherence-and-save-time"><span class="header-section-number">7</span> Why Adopting these Policies would
Improve Coherence and Save Time<a href="#why-adopting-these-policies-would-improve-coherence-and-save-time" class="self-link"></a></h1>
<h2 data-number="7.1" id="advantages"><span class="header-section-number">7.1</span> Advantages<a href="#advantages" class="self-link"></a></h2>
<ul>
<li><p><strong>Consistency and iteroperability</strong>: Having a
consistent allocator-aware infrastructure allows the various types that
allocate memory to work together as building blocks that give the
programmer control over how memory is allocated and used.</p></li>
<li><p><strong>Time savings</strong>: The LEWG has spent many hours
debating, in person and on the reflector, whether this class or that
should take an allocator. These policies should short-circuit most of
those debates.</p></li>
<li><p><strong>Better-initial-quality proposals</strong>: There have
been many instances in my memory where a type was proposed without
allocators and needed to be reworked to enable allocator use. Having
these policies in the <em>checklist</em> of LEWG policies should enable
paper authors to come to the committee with higher-quality and more
complete proposals.</p></li>
</ul>
<h2 data-number="7.2" id="disadvantages"><span class="header-section-number">7.2</span> Disadvantages<a href="#disadvantages" class="self-link"></a></h2>
<ul>
<li><p><strong>Bigger interfaces</strong>: Allocators make the class
specification more complex.</p></li>
<li><p><strong>More implementation complexity</strong>: Allocators make
implementation more difficult.</p></li>
<li><p><strong>Longer compile times</strong>: The flexibility afforded
by the C++11 allocator model increases compile time by introducing
metaprogramming based on
<code class="sourceCode default">allocator_traits</code> and propagation
traits.</p></li>
</ul>
<p>In considering the first two disadvantages, bear in mind that our
main task is to make C++ as useful as possible for programmers, not to
make our job easier when writing interface specifications or
implementing the Standard Library itself. It has been shown repeatedly
that beginners can ignore allocators as a rule and tutorials for
beginners can discuss allocators in more advanced sections.</p>
<p>The third issue can be mitigated significantly by specializing a
class template specifically for
<code class="sourceCode default">std::allocator</code>. Such a
specialization need not use
<code class="sourceCode default">allocator_traits</code> or consider
propagation traits at all, and so should be almost as fast to compile
(and run) as a non-allocator-aware class, yet the facility is still
allocator-aware for users that want it.</p>
<h1 data-number="8" id="proposed-sd-9-wording"><span class="header-section-number">8</span> Proposed SD-9 Wording<a href="#proposed-sd-9-wording" class="self-link"></a></h1>
<p>Append to “List of Standard Library Policies” section of SD-9, the
following policies. Note that the policy numbers are relative to the
overall numbering of policies in SD-9.</p>
<ol type="1">
<li><p>A class that allocates memory should be <em>allocator-aware</em>,
and should conform to as many of the <em>allocator-aware container</em>
requirements (section <span>24.2.2.5
<a href="https://wg21.link/N4971#container.alloc.reqmts">[container.alloc.reqmts]</a></span>)
as apply, even for non-contaianers — requirements on
<code class="sourceCode default">T</code> are interpreted as
requirements on any type potentially constructed within the allocated
memory.</p></li>
<li><p>If it can be shown that applying the previous policy and making a
class allocator-aware would incur excessive cost (in compile- and/or
run-time), then the allocator-aware behavior can be separated out into a
separate class, typically using the same name with the prefix,
“<code class="sourceCode default">basic_</code>”.</p></li>
<li><p>The allocator type for an allocator-aware class should be
optional and default to a specialization of
<code class="sourceCode default">std::allocator</code>.</p></li>
<li><p>For each allocator-aware class template, there should be an alias
in the <code class="sourceCode default">std::pmr</code> namespace where
the allocator type is specified as
<code class="sourceCode default">std::pmr::polymorphic_allocator</code>.
If the allocator-aware class name begins with the
<code class="sourceCode default">basic_</code> prefix, the
<code class="sourceCode default">std::pmr</code> alias name should
typically <em>not</em> have the prefix.</p></li>
<li><p>A class that contains subobjects (base classes or members) that
might use allocators should accept an allocator,
<code class="sourceCode default">A</code>, at construction amd forward
it to those subobjects via <em>uses-allocator construction</em> with
allocator <code class="sourceCode default">A</code> (<span>20.2.8.2
<a href="https://wg21.link/N4971#allocator.uses.construction">[allocator.uses.construction]</a></span>).
If such a class, <code class="sourceCode default">X</code>, does not
define <code class="sourceCode default">allocator_type</code>, then
<code class="sourceCode default">std::uses_allocator&lt;X, Alloc&gt;</code>
should be specialized to derive from
<code class="sourceCode default">true_type</code> for all acceptable
allocator types, <code class="sourceCode default">Alloc</code> (see
<span>20.2.8.1
<a href="https://wg21.link/N4971#allocator.uses.trait">[allocator.uses.trait]</a></span>).
Such a class is called <em>allocator-enabled</em>, but is not
necessarily <em>allocator-aware</em>.</p></li>
<li><p>An object within allocator-provided memory should be constructed
by invoking <code class="sourceCode default">allocator_traits&lt;Alloc&gt;::construct</code>.
For the purpose at this policy, a <em>dynamically sized</em> buffer is
treated as allocated memory, even if it happens to reside in the
object’s footprint when below a certain size (i.e., the small-object
optimization); otherwise it is treated as a member variable (see
previous policy).</p></li>
<li><p>If a class is allocator-aware or allocator-enabled, then every
constructor should have a variant (via overloading or default arguments)
that takes an allocator parameter. This quality enables
<em>uses-allocator construction</em> in generic contexts (see
<span>20.2.8.2
<a href="https://wg21.link/N4971#allocator.uses.construction">[allocator.uses.construction]</a></span>).</p></li>
<li><p>An allocator-enabled <em>wrapper</em> class should, when
possible, deduce an its
<code class="sourceCode default">allocator_type</code> from the class it
is wrapping.</p></li>
</ol>
<h1 data-number="9" id="bibliography"><span class="header-section-number">9</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" role="doc-bibliography">
<div id="ref-Halpern2017" class="csl-entry" role="doc-biblioentry">
[Halpern2017] Pablo Halpern. Allocators, The Good Parts. <a href="https://youtu.be/v3dz-AKOVL8?si=mi5JOJMaqD6lvRqv"><div class="csl-block">https://youtu.be/v3dz-AKOVL8?si=mi5JOJMaqD6lvRqv</div></a>
</div>
<div id="ref-P0429R3" class="csl-entry" role="doc-biblioentry">
[P0429R3] Zach Laine. 2016-08-31. A Standard flat_map. <a href="https://wg21.link/p0429r3"><div class="csl-block">https://wg21.link/p0429r3</div></a>
</div>
<div id="ref-P1222R0" class="csl-entry" role="doc-biblioentry">
[P1222R0] Zach Laine. 2018-10-02. A Standard flat_set. <a href="https://wg21.link/p1222r0"><div class="csl-block">https://wg21.link/p1222r0</div></a>
</div>
<div id="ref-P2035R0" class="csl-entry" role="doc-biblioentry">
[P2035R0] Pablo Halpern, John Lakos. 2020-01-13. Value Proposition:
Allocator-Aware (AA) Software. <a href="https://wg21.link/p2035r0"><div class="csl-block">https://wg21.link/p2035r0</div></a>
</div>
<div id="ref-P2127R0" class="csl-entry" role="doc-biblioentry">
[P2127R0] Pablo Halpern. Making C++ Software Allocator Aware. <a href="http://wg21.link/P2127R0"><div class="csl-block">http://wg21.link/P2127R0</div></a>
</div>
<div id="ref-P2267R1" class="csl-entry" role="doc-biblioentry">
[P2267R1] Inbal Levi, Ben Craig, Fabio Fracassi. 2023-11-23. Library
Evolution Policies. <a href="https://wg21.link/p2267r1"><div class="csl-block">https://wg21.link/p2267r1</div></a>
</div>
<div id="ref-Sutter2016" class="csl-entry" role="doc-biblioentry">
[Sutter2016] Herb Sutter. Leak-Freedom in C++… By Default. <a href="https://youtu.be/JfmTagWcqoE?si=OZ7EeziRKPaDnHSx"><div class="csl-block">https://youtu.be/JfmTagWcqoE?si=OZ7EeziRKPaDnHSx</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 N4971 unless otherwise specified.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>Note that, due to some last-minute
concerns, P2127 might not be published in time for the pre-Tokyo
mailing, but should be available shortly after the mailing is sent
out.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>
