<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-05-18" />
  <title>Type-aware allocation and deallocation functions</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: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }

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

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

code.sourceCode > span { display: inline; }
</style>
  <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">Type-aware allocation and
deallocation functions</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P2719R0</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-05-18</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>
      Evolution<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Louis Dionne<br>&lt;<a href="mailto:ldionne@apple.com" class="email">ldionne@apple.com</a>&gt;<br>
      Oliver Hunt<br>&lt;<a href="mailto:oliver@apple.com" class="email">oliver@apple.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<h1 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>C++ currently provides two ways of customizing the creation of
objects in new expressions. First,
<code class="sourceCode default">operator new</code> can be provided as
a static member function of a class, like
<code class="sourceCode default">void* T::operator new</code>. If such a
declaration is provided, an expression like
<code class="sourceCode default">new T(...)</code> will use that
allocation function. Otherwise, the global version of
<code class="sourceCode default">operator new</code> can be replaced by
users in a type-agnostic way, by implementing
<code class="sourceCode default">void* operator new(size_t)</code> and
its variants. A similar mechanism exists for
<em>delete-expressions</em>.</p>
<p>This paper proposes an extension to the way <em>new-expressions</em>
and <em>delete-expressions</em> select their allocation and deallocation
function to provide the power of the in-class operator variant, which
retains the knowledge of the type being allocated/deallocated, without
requiring the intrusive definition of an in-class function. This is
achieved by tweaking the search already performed by
<em>new-expressions</em> and <em>delete-expressions</em> to also include
a call to any free function
<code class="sourceCode default">operator new</code> with an additional
tag parameter of
<code class="sourceCode default">std::type_identity&lt;T&gt;</code>. The
following describes (roughly) the search process performed by the
compiler before and after this paper:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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="co">// user writes:</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">new</span> <span class="op">(</span>args<span class="op">...)</span> T<span class="op">(...)</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="co">// compiler checks (in order):</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, args<span class="op">...)</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, args<span class="op">...)</span></span></code></pre></div>

</div></td>
<td><div>

<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><span class="co">// user writes:</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw">new</span> <span class="op">(</span>args<span class="op">...)</span> T<span class="op">(...)</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="co">// compiler checks (in order):</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, args<span class="op">...)</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>operator new(sizeof(T), type_identity&lt;T&gt;{}, args…)</ins></span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, args<span class="op">...)</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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="co">// user writes:</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="kw">new</span> <span class="op">(</span>args<span class="op">...)</span> T<span class="op">[</span>n<span class="op">]</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="co">// compiler checks (in order):</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span><span class="op">[](</span>n<span class="op">*</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, args<span class="op">...)</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span><span class="op">[](</span>n<span class="op">*</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, args<span class="op">...)</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="co">// user writes:</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">new</span> <span class="op">(</span>args<span class="op">...)</span> T<span class="op">[</span>n<span class="op">]</span>;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="co">// compiler checks (in order):</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span><span class="op">[](</span>n<span class="op">*</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, args<span class="op">...)</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>operator new[](n*sizeof(T), type_identity&lt;T&gt;{}, args…)</ins></span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span><span class="op">[](</span>n<span class="op">*</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, args<span class="op">...)</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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><span class="co">// user writes:</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">delete</span> ptr</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="co">// compiler checks (in order):</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>T<span class="op">::</span><span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span><span class="dt">void</span><span class="op">-</span>ptr<span class="op">)</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="op">::</span><span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span><span class="dt">void</span><span class="op">-</span>ptr<span class="op">)</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co">// user writes:</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">delete</span> ptr</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="co">// compiler checks (in order):</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>T<span class="op">::</span><span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span><span class="dt">void</span><span class="op">-</span>ptr<span class="op">)</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>operator delete(void-ptr, type_identity&lt;T&gt;{})</ins></span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a><span class="op">::</span><span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span><span class="dt">void</span><span class="op">-</span>ptr<span class="op">)</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Before</strong>
</div></th>
<th><div style="text-align:center">
<strong>After</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div>

<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="co">// user writes:</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">delete</span><span class="op">[]</span> ptr</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="co">// compiler checks (in order):</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>T<span class="op">::</span><span class="kw">operator</span> <span class="kw">delete</span><span class="op">[](</span><span class="dt">void</span><span class="op">-</span>ptr<span class="op">)</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="op">::</span><span class="kw">operator</span> <span class="kw">delete</span><span class="op">[](</span><span class="dt">void</span><span class="op">-</span>ptr<span class="op">)</span></span></code></pre></div>

</div></td>
<td><div>

<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="co">// user writes:</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">delete</span><span class="op">[]</span> ptr</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="co">// compiler checks (in order):</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>T<span class="op">::</span><span class="kw">operator</span> <span class="kw">delete</span><span class="op">[](</span><span class="dt">void</span><span class="op">-</span>ptr<span class="op">)</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>operator delete[](void-ptr, type_identity&lt;T&gt;{})</ins></span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a><span class="op">::</span><span class="kw">operator</span> <span class="kw">delete</span><span class="op">[](</span><span class="dt">void</span><span class="op">-</span>ptr<span class="op">)</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<h1 data-number="2" id="motivation"><span class="header-section-number">2</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>Knowledge of the type being allocated in a <em>new-expression</em> is
necessary in order to achieve certain levels of flexibility when
defining a custom allocation function. However, requiring an intrusive
in-class definition to achieve this is not realistic in various
circumstances, for example when wanting to customize allocation for
types that are controlled by a third-party, or when customizing
allocation for a very large number of types.</p>
<p>In the wild, we often see code bases overriding the global (and
untyped) <code class="sourceCode default">operator new</code> via the
usual link-time mechanism and running into issues because they really
only intended for their custom
<code class="sourceCode default">operator new</code> to be used within
their own code, not by all the code in their process. We also run into
issues where multiple libraries attempt to replace the global
<code class="sourceCode default">operator new</code> and end up with a
complex ODR violation bug. The simple change proposed by this paper
provides a way for most code bases to achieve what they
<em>actually</em> want, which is to override
<code class="sourceCode default">operator new</code> for a family of
types that they control without overriding it for the whole process. The
overriding also happens at compile-time instead of link-time, which is
both supported by all known implementations (unlike link-time) and
better understood by users than e.g. weak definitions.</p>
<h2 data-number="2.1" id="a-concrete-use-case"><span class="header-section-number">2.1</span> A concrete use case<a href="#a-concrete-use-case" class="self-link"></a></h2>
<p>A few years ago, Apple published <a href="https://security.apple.com/blog/towards-the-next-generation-of-xnu-memory-safety">a
blog post</a> explaining a technique used inside its kernel (XNU) to
mitigate various exploits. At its core, the technique roughly consists
in allocating objects of each type in a different bucket. By collocating
all objects of the same type into the same region of memory, it becomes
much harder for an attacker to exploit a type confusion vulnerability.
Since its introduction in the kernel, this technique alone has been by
far the most effective at mitigating type confusion vulnerabilities.</p>
<p>In a world where security is increasingly important, it may make
sense for some code bases to adopt mitigation techniques such as this
one. However, these techniques require a large-scale and <em>almost</em>
system-wide customization of how allocation is performed while retaining
type information, which is not supported by C++ today. While not
sufficient in itself to make C++ safer, the change proposed in this
paper is a necessary building block for technology such as the above
which can greatly improve the security of C++ applications.</p>
<h1 data-number="3" id="current-behavior-recap"><span class="header-section-number">3</span> Current behavior recap<a href="#current-behavior-recap" class="self-link"></a></h1>
<p>Today, the compiler performs <a href="https://timsong-cpp.github.io/cppwp/n4950/expr.new#12">a
lookup</a> in the allocated type’s class scope (for
<code class="sourceCode default">T::operator new</code>), and then a
lookup in the global scope (for
<code class="sourceCode default">::operator new</code>) if the previous
one failed. Once the name lookup has been done and the compiler has
decided whether it was looking for
<code class="sourceCode default">T::operator new</code> or
<code class="sourceCode default">::operator new</code>, name lookup will
not be done again even if the steps that follow were to fail.</p>
<p>The compiler then performs <a href="https://timsong-cpp.github.io/cppwp/n4950/expr.new#19">overload
resolution</a> on the name it found in the previous step (let’s call
that name <code class="sourceCode default">NEW</code>) by assembling an
argument list that depends on whether
<code class="sourceCode default">T</code> has a new-extended alignment
or not. For the sake of simplicity, assume that
<code class="sourceCode default">T</code> does not have a new-extended
alignment. The compiler starts by performing overload resolution as-if
the following expression were used:</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>NEW<span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, args<span class="op">...)</span></span></code></pre></div>
<p>If that succeeds, the compiler selects the overload that won. If it
does not, the compiler performs overload resolution again as-if the
following expression were used:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>NEW<span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, std<span class="op">::</span>align_val_t<span class="op">(</span><span class="kw">alignof</span><span class="op">(</span>T<span class="op">))</span>, args<span class="op">...)</span></span></code></pre></div>
<p>If that succeeds, the compiler selects the overload that won. If it
does not, the program is ill-formed. For a type
<code class="sourceCode default">T</code> that has new-extended
alignment, the order of the two overload resolutions performed above is
simply reversed.</p>
<p>Delete-expressions behave similarly, with lookup being performed in
the context of the dynamic type of the object, in case it differs from
its static type. The overload resolution process then works by
preferring a destroying delete, followed by an aligned delete (if the
type has new-extended alignment), followed by the usual
<code class="sourceCode default">operator delete</code> (with or without
a <code class="sourceCode default">size_t</code> parameter depending on
whether the considered
<code class="sourceCode default">operator delete</code> is a member
function or not).</p>
<h1 data-number="4" id="proposal"><span class="header-section-number">4</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>Our proposal essentially adds a new step in the resolution above that
also considers a free function
<code class="sourceCode default">operator new</code> after it considers
a member <code class="sourceCode default">T::operator new</code>, but
before the global
<code class="sourceCode default">::operator new</code>. That free
function is called as</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;{}</span>, placement<span class="op">-</span>args<span class="op">...)</span></span></code></pre></div>
<p>In particular, this means that it triggers ADL, which allows defining
such an operator in e.g. a custom namespace. We mostly discuss
<code class="sourceCode default">operator new</code> below, but
<code class="sourceCode default">operator new[]</code>,
<code class="sourceCode default">operator delete</code> and
<code class="sourceCode default">operator delete[]</code> are all
handled analogously.</p>
<h2 data-number="4.1" id="wording-approach"><span class="header-section-number">4.1</span> Wording approach<a href="#wording-approach" class="self-link"></a></h2>
<p>This proposal is best explained as two distinct changes to the
existing rules explained above. First, observe how we currently perform
name lookup first to fix the name we’re using (either
<code class="sourceCode default">T::operator new</code> or
<code class="sourceCode default">::operator new</code>), and then
perform overload resolution to find the best candidate given that name.
This needs to change because if we introduce a free function in the mix
that is found by ADL, we could often end up finding that free function
as the result of name lookup. However, the mere presence of such a free
function doesn’t guarantee at all that it is a viable candidate given
the arguments we have (for example if the free function merely happened
to be in one of the namespaces we looked in). As a result, we could
often end up in a situtation where
<code class="sourceCode default">new Foo(...)</code> fails during
overload resolution simply because a non-viable
<code class="sourceCode default">operator new</code> free function was
located in one of <code class="sourceCode default">Foo</code>’s
associated namespaces.</p>
<p>Consequently, the first change we need to make is to perform name
lookup for <code class="sourceCode default">T::operator new</code>, and
if found, then perform overload resolution on that name immediately. If
overload resolution fails, then go on to the next candidate (which is
<code class="sourceCode default">::operator new</code>) and perform
overload resolution on that name. This change can be seen as a
relaxation of the current rules and cannot affect any existing valid
program. Indeed, code where
<code class="sourceCode default">T::operator new</code> is currently
selected but where overload resolution fails actually doesn’t compile
today, since the compiler falls flat after failing to perform overload
resolution. After this change, such code would now fall back to trying
overload resolution on
<code class="sourceCode default">::operator new</code>, which might
succeed.</p>
<p>The second change we need to make is the addition of a new step in
the search, between
<code class="sourceCode default">T::operator new</code> and
<code class="sourceCode default">::operator new</code>. Assuming that
the name lookup or the overload resolution for
<code class="sourceCode default">T::operator new</code> fails, we would
now perform an argument-dependent name lookup for a free function named
<code class="sourceCode default">operator new</code> as-if we had the
following expression:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;{}</span>, args<span class="op">...)</span></span></code></pre></div>
<p>In other words, the set of associated namespaces would include the
<code class="sourceCode default">std</code> namespace (via
<code class="sourceCode default">std::type_identity</code>), the
associated namespaces of <code class="sourceCode default">T</code> (by
virtue of the template parameter of
<code class="sourceCode default">std::type_identity</code>), and that of
any other provided placement-arguments. In particular, note that this
may or may not include the global namespace.</p>
<p>If this name lookup succeeds, we would perform overload resolution on
this function in a way similar to what we currently do in <a href="https://timsong-cpp.github.io/cppwp/n4950/expr.new#19">expr.new#19</a>,
but tweaked to take into account the
<code class="sourceCode default">std::type_identity</code> argument:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co">// first resolution attempt</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;{}</span>, args<span class="op">...)</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="co">// second resolution attempt</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, std<span class="op">::</span>align_val_t<span class="op">(</span><span class="kw">alignof</span><span class="op">(</span>T<span class="op">))</span>, std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;{}</span>, args<span class="op">...)</span></span></code></pre></div>
<p>For a type with new-extended alignment, we simply reverse the order
of these overload resolution attempts. If this overload resolution
fails, we would then move on to the next candidate found by name lookup,
which is <code class="sourceCode default">::operator new</code>, and we
would perform the usual overload resolution on it.</p>
<p>Delete expressions or array new/delete expressions work in a way
entirely analoguous to what is described above for single-object
new-expressions.</p>
<h2 data-number="4.2" id="example"><span class="header-section-number">4.2</span> Example<a href="#example" class="self-link"></a></h2>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> lib <span class="op">{</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> Foo <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span><span class="op">*</span> <span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span>, std<span class="op">::</span>type_identity<span class="op">&lt;</span>Foo<span class="op">&gt;)</span>; <span class="co">// (1)</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> Foo2 <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Bar <span class="op">{</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="dt">void</span><span class="op">*</span> <span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>; <span class="co">// (2)</span></span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span><span class="op">*</span> <span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>; <span class="co">// (3)</span></span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">()</span> <span class="op">{</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> lib<span class="op">::</span>Foo<span class="op">()</span>;  <span class="co">// calls (1)</span></span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> Bar<span class="op">()</span>;       <span class="co">// calls (2)</span></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> lib<span class="op">::</span>Foo2<span class="op">()</span>; <span class="co">// (1) is seen but fails overload resolution, we end up calling (3)</span></span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> <span class="dt">int</span><span class="op">()</span>;       <span class="co">// calls (3)</span></span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h1 data-number="5" id="design-choices-and-notes"><span class="header-section-number">5</span> Design choices and notes<a href="#design-choices-and-notes" class="self-link"></a></h1>
<h2 data-number="5.1" id="impact-on-the-library"><span class="header-section-number">5.1</span> Impact on the library<a href="#impact-on-the-library" class="self-link"></a></h2>
<p>This proposal does not have any impact on the library, since this
only tweaks the search process performed by the compiler when it
evaluates a new-expression and a delete-expression. In particular, we do
not propose adding new type-aware free function
<code class="sourceCode default">operator new</code> variants in the
standard library at this time, althought this could be investigated in
the future.</p>
<h2 data-number="5.2" id="design-choice-order-of-arguments"><span class="header-section-number">5.2</span> Design choice: Order of
arguments<a href="#design-choice-order-of-arguments" class="self-link"></a></h2>
<p>When writing this paper, we went back and forth of the order of
arguments. This paper proposes:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span>, std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, placement<span class="op">-</span>args<span class="op">...)</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span>, std<span class="op">::</span>align_val_t, std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, placement<span class="op">-</span>args<span class="op">...)</span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span><span class="dt">void</span><span class="op">*</span>, std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;)</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span><span class="dt">void</span><span class="op">*</span>, std<span class="op">::</span><span class="dt">size_t</span>, std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;)</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span><span class="dt">void</span><span class="op">*</span>, std<span class="op">::</span><span class="dt">size_t</span>, std<span class="op">::</span>align_val_t, std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;)</span></span></code></pre></div>
<p>Another approach would be:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span>std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span>, placement<span class="op">-</span>args<span class="op">...)</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span>std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span>, std<span class="op">::</span>align_val_t, placement<span class="op">-</span>args<span class="op">...)</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span>std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, <span class="dt">void</span><span class="op">*)</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span>std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, <span class="dt">void</span><span class="op">*</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span>std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, <span class="dt">void</span><span class="op">*</span>, std<span class="op">::</span><span class="dt">size_t</span>, std<span class="op">::</span>align_val_t<span class="op">)</span></span></code></pre></div>
<p>We would like input from EWG on this matter.</p>
<h2 data-number="5.3" id="design-choice-template-argument-vs-stdtype_identity"><span class="header-section-number">5.3</span> Design choice: Template
argument vs <code class="sourceCode default">std::type_identity</code><a href="#design-choice-template-argument-vs-stdtype_identity" class="self-link"></a></h2>
<p>In an earlier draft, this paper was proposing the following
(seemingly simpler) mechanism instead. Instead of reusing
<code class="sourceCode default">std::type_identity</code>, the compiler
would search as per the following expression:</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">new</span><span class="op">&lt;</span>T<span class="op">&gt;(</span><span class="kw">sizeof</span><span class="op">(</span>T<span class="op">)</span>, args<span class="op">...)</span></span></code></pre></div>
<p>The only difference here is that we’re not passing
<code class="sourceCode default">std::type_identity</code> as a first
argument and we are passing it as a template argument instead.
Unfortunately, this has two problems. First, this doesn’t allow ADL to
kick in, severely reducing the flexibility for defining the operator.
The second problem is that existing code is allowed to have defined a
global <code class="sourceCode default">operator new</code> like so:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> <span class="op">...</span>Args<span class="op">&gt;</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span><span class="op">*</span> <span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span> size, Args <span class="op">...</span>args<span class="op">)</span>;</span></code></pre></div>
<p>We believe that this is not a far fetched possibility and that we may
break some code if we went down that route. Even worse, an existing
templated <code class="sourceCode default">operator new</code> could
match even though it was never intended to be called. The result would
be that the first template argument is explicitly provided by the
compiler, which could result in a substitution failure (that is
acceptable) or in a valid function call triggering an implicit
conversion to the now-explicitly-provided first template argument, which
would change the meaning of valid programs.</p>
<h2 data-number="5.4" id="design-choice-no-stdtype_identity-for-operator-delete"><span class="header-section-number">5.4</span> Design choice: No
<code class="sourceCode default">std::type_identity</code> for
<code class="sourceCode default">operator delete</code><a href="#design-choice-no-stdtype_identity-for-operator-delete" class="self-link"></a></h2>
<p>We could perhaps simplify the design for delete-expressions by
passing the type of the object directly:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span>T<span class="op">*&gt;(</span>ptr<span class="op">)</span>, std<span class="op">::</span>destroying_delete<span class="op">)</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span>T<span class="op">*&gt;(</span>ptr<span class="op">)</span>, std<span class="op">::</span>destroying_delete, std<span class="op">::</span>align_val_t<span class="op">(</span><span class="kw">alignof</span><span class="op">(</span>T<span class="op">)))</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>DELETE(static_cast&lt;T*&gt;(ptr))</ins></span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">void</span><span class="op">*&gt;(</span>ptr<span class="op">))</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><span class="add" style="color: #006e28"><ins>DELETE(static_cast&lt;T*&gt;(ptr),
std::align_val_t(alignof(T)))</ins></span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span><span class="kw">static_cast</span><span class="op">&lt;</span><span class="dt">void</span><span class="op">*&gt;(</span>ptr<span class="op">)</span>, std<span class="op">::</span>align_val_t<span class="op">(</span><span class="kw">alignof</span><span class="op">(</span>T<span class="op">)))</span></span></code></pre></div>
<p>However, we believe that having using a tag type makes it clearer
that typed deallocation functions do not destroy the object, and this
also allows keeping the
<code class="sourceCode default">operator delete</code> call consistent
with the <code class="sourceCode default">operator new</code> call,
which is a nice property.</p>
<h2 data-number="5.5" id="is-the-current-name-lookup-for-toperator-new-done-this-way-on-purpose"><span class="header-section-number">5.5</span> Is the current name lookup for
<code class="sourceCode default">T::operator new</code> done this way on
purpose?<a href="#is-the-current-name-lookup-for-toperator-new-done-this-way-on-purpose" class="self-link"></a></h2>
<p>Currently, the search that happens for a new-expression is worded
such that if a <code class="sourceCode default">T::operator new</code>
is found and overload resolution fails, the program is ill-formed. As
explained in this proposal, this is stricter than needed and we propose
relaxing that.</p>
<p>However, one side effect of this strictness is that the compiler will
error if a user defines some variants of
<code class="sourceCode default">T::operator new</code> but forgets to
define some other variants. <a href="https://godbolt.org/z/vEsc81h59">For example</a>:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> arg <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Foo <span class="op">{</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="dt">void</span><span class="op">*</span> <span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span>, arg<span class="op">)</span>;</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">()</span> <span class="op">{</span></span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> Foo<span class="op">()</span>;</span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Today, this is a compiler error because we find
<code class="sourceCode default">Foo::operator new</code> and then fail
to perform overload resolution, so we don’t fall back to the global
<code class="sourceCode default">::operator new</code>. I don’t know
whether this is by design or just an unintended consequence of the
wording, however this seems a bit contrived.</p>
<p>In all cases, if we wanted this to remain ill-formed, we could either
count on compiler diagnostics to warn in that case, or we could word the
search process to say that if the overload resolution on
<code class="sourceCode default">T::operator new</code> fails, the
program is ill-formed and the search stops. This doesn’t seem useful to
me, but it’s on the table.</p>
<!--
## Should a templated operator delete be allowed as a usual allocation function?

[dynamic.deallocation#3](https://timsong-cpp.github.io/cppwp/n4950/basic.stc.dynamic.deallocation#3) states that a template function
is never considered as a usual allocation function. This prevents general allocators from specifying a general type-aware deallocation
operator that can reflect the correct concrete type when invoking a deleting constructor. e.g.

```cpp
class Root {
public:
  template <class T> static void *operator new(std::size_t, std::type_identity<T>);
  template <class T> static void operator delete(void *, std::type_identity<T>);
};

class A : public Root { };

class B : public Root {
  virtual ~B();
};
class C : public B { };

int foo(A* a, B* b, B* c /* actually points to a C object */) {
  delete a; // We want Root::operator delete<A>(...) to be called

  delete b; // We want Root::operator delete<B> to be called, and that happens via
            // the deleting virtual destructor.
            // TODO

  delete c; // The allocator would call the deleting virtual destructor, and expect this to invoke
            // Root::operator delete<C>
            // TODO
}
```

Allowing a template delete operator to be considered a usual allocation function could result in previously ignored delete declarations being invoked. We could mitigate this risk by constraining the selection of template `usual` allocations to solely allow the typed allocation signatures - the existing selection rules for usual allocation functions already have strict parameter type restrictions on what is required for an allocation function to be usual so this is not wholly without precedence.
-->
<h1 data-number="6" id="suggested-polls"><span class="header-section-number">6</span> Suggested polls<a href="#suggested-polls" class="self-link"></a></h1>
<ol type="1">
<li>Do we want to solve the problem of providing a type aware
<code class="sourceCode default">operator new</code> as a free
function?</li>
<li>Do we prefer
<code class="sourceCode default">std::type_identity</code> after the
size and alignment (status quo), or first in the argument list?</li>
</ol>
</div>
</div>
</body>
</html>
