<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<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="2025-02-10" />
  <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>
      P2719R4
      [<a href="https://wg21.link/P2719">Latest</a>]
      [<a href="https://wg21.link/P2719/status">Status</a>]
    </td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2025-02-10</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>
      CWG<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">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction<span></span></a></li>
<li><a href="#revision-history" id="toc-revision-history"><span class="toc-section-number">2</span> Revision
history<span></span></a></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">3</span> Motivation<span></span></a></li>
<li><a href="#current-behavior-recap" id="toc-current-behavior-recap"><span class="toc-section-number">4</span> Current behavior
recap<span></span></a></li>
<li><a href="#proposal" id="toc-proposal"><span class="toc-section-number">5</span> Proposal<span></span></a></li>
<li><a href="#proposed-wording" id="toc-proposed-wording"><span class="toc-section-number">6</span> Proposed
wording<span></span></a></li>
<li><a href="#design-choices-and-notes" id="toc-design-choices-and-notes"><span class="toc-section-number">7</span> Design choices and
notes<span></span></a></li>
<li><a href="#acknowledgments" id="toc-acknowledgments"><span class="toc-section-number">8</span>
Acknowledgments<span></span></a></li>
</ul>
</div>
<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 cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
can be provided as a static member function of a class, like <code class="sourceCode cpp"><span class="dt">void</span><span class="op">*</span> T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>.
If such a declaration is provided, an expression like <code class="sourceCode cpp"><span class="kw">new</span> T<span class="op">(...)</span></code>
will use that allocation function. Otherwise, the global version of
<code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
can be replaced by users in a type-agnostic way, by implementing <code class="sourceCode cpp"><span class="dt">void</span><span class="op">*</span> <span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span><span class="dt">size_t</span><span class="op">)</span></code>
and its variants. A similar mechanism exists for
<em>delete-expressions</em>.</p>
<p>This paper proposes an extension to <em>new-expressions</em> and
<em>delete-expressions</em> to provide the concrete type being
[de]allocated to the allocation functions. This is achieved via the use
of an additional <code class="sourceCode cpp">std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
tag argument that allows the provision of the concrete type to <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
and <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>.
In addition to providing valuable information to the allocator, this
allows the creation of type-specific <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
and <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
for types that cannot have intrusive class-scoped operators
specified.</p>
<p>At a high level, this allows defining allocation and deallocation
functions like:</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="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>type_identity<span class="op">&lt;</span>mylib<span class="op">::</span>Foo<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span> n<span class="op">)</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <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>mylib<span class="op">::</span>Foo<span class="op">&gt;</span>, <span class="dt">void</span><span class="op">*</span> ptr<span class="op">)</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span></code></pre></div>
<p>However, it also allows providing these functions for a family of
types, which is where this feature becomes interesting:</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><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> use_special_allocation_scheme<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb2-3"><a href="#cb2-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>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span> n<span class="op">)</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-5"><a href="#cb2-5" 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="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span> use_special_allocation_scheme<span class="op">&lt;</span>T<span class="op">&gt;</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <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> ptr<span class="op">)</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span></code></pre></div>
<h1 data-number="2" id="revision-history"><span class="header-section-number">2</span> Revision history<a href="#revision-history" class="self-link"></a></h1>
<ul>
<li>R0 (St-Louis): Initial version</li>
<li>R1 (pre-Wroclaw):
<ul>
<li>Simplified the lookup mechanism by removing the need to perform ADL
(based on implementation experience)</li>
<li>Allowed <code class="sourceCode cpp">std<span class="op">::</span>type_identity</code>
parameter for in-class <code class="sourceCode cpp">T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>
for consistency</li>
<li>Made <code class="sourceCode cpp">std<span class="op">::</span>type_identity</code>
as the first parameter</li>
<li>Documented design choices and changes based on feedback and
implementation experience</li>
</ul></li>
<li>R2 (Wroclaw):
<ul>
<li>Added the initial wording</li>
</ul></li>
<li>R3 (pre-Hagenberg):
<ul>
<li>Added design choices for EWG review:
<ul>
<li>On <a href="#design-choice-allowing-type-aware-allocation-functions-in-constant-expressions">constant
expression evaluation</a></li>
<li>On <a href="#design-choice-stripping-qualifiers-from-the-type">stripping
qualifiers</a></li>
<li>On <a href="#design-choice-safety-restriction-on-mismatched-declaration-scopes">enforcing
matched declaration scopes</a></li>
</ul></li>
<li>Mention interactions with coroutines</li>
<li>More comprehensive wording
<ul>
<li>Include feature detection macro</li>
<li>Better explain the content of the type-identity parameter in <code class="sourceCode cpp"><span class="op">[</span>expr<span class="op">.</span><span class="kw">new</span><span class="op">]</span></code>
and <code class="sourceCode cpp"><span class="op">[</span>expr<span class="op">.</span><span class="kw">delete</span><span class="op">]</span></code></li>
<li>Make it explicit that a type aware operator delete cannot be a
destroying delete</li>
<li>Include language to allow type-aware <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
in constant expressions</li>
</ul></li>
<li>Incorporated wording feedback from Brian, Corentin, and Richard
(thanks!)</li>
</ul></li>
<li>R4 (EWG in Hagenberg):
<ul>
<li>Added design choice for EWG review on <a href="#design-choice-all-implicit-parameters-are-mandatory">mandatory
implicit parameters</a></li>
</ul></li>
</ul>
<h1 data-number="3" id="motivation"><span class="header-section-number">3</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>Knowledge of the type being [de]allocated in a
<em>new-expression</em> is necessary in order to achieve certain levels
of flexibility when defining a custom allocation function. However, even
when defining <code class="sourceCode cpp">T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>
in-class, the only information available to the implementation is the
type declaring the operator, not the type being allocated. This results
in developers various creative (often macro-based) mechanisms to define
these allocation functions manually, or circumventing the
language-provided allocation mechanisms entirely in order to track the
allocated types.</p>
<p>However, in addition to these intrusive mechanisms being cumbersome
and error-prone, they do not make it possible to customize how
allocation is performed for types controlled by a third-party, or to
customize allocation for an open set of types.</p>
<p>Beyond these issues, a common problem in we see in the wild is
codebases overriding the global (and untyped) <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
via the usual link-time mechanism and running into problems because they
really only intended for their custom <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
to be used within their own code, not by all the code in their process.
For example, we’ve seen scenarios where multiple libraries attempt to
replace the global <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
and end up with a complex ODR violation bug that depends on how the
dynamic linker resolved weak definitions at load time – not very user
friendly. By providing the concrete type information to allocators at
compile time, it becomes possible for authors to override <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
for a family of types that they control without overriding it for the
whole process, which is what they <em>actually</em> want.</p>
<h2 data-number="3.1" id="a-concrete-use-case"><span class="header-section-number">3.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="4" id="current-behavior-recap"><span class="header-section-number">4</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 cpp">T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>),
and then a lookup in the global scope (for <code class="sourceCode cpp"><span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></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 cpp">T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>
or <code class="sourceCode cpp"><span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>,
name lookup will not be done again even if the steps that follow were to
fail. From here on, let’s denote by
<code class="sourceCode cpp">NEW</code> the set of candidates found by
the name lookup process.</p>
<p>The compiler then performs <a href="https://timsong-cpp.github.io/cppwp/n4950/expr.new#19">overload
resolution</a> on that set of candidates using the language-specified
optional implicit parameters, and if present any developer-provided
placement arguments. It does so by assembling an argument list that
depends on whether <code class="sourceCode cpp">T</code> has a
new-extended alignment or not. For the sake of simplicity, assume that
<code class="sourceCode cpp">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="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-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="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-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 cpp">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 static type of the expression. 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 cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
(with or without a
<code class="sourceCode cpp"><span class="dt">size_t</span></code>
parameter depending on whether the considered <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
is a member function or not).</p>
<h1 data-number="5" id="proposal"><span class="header-section-number">5</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>This proposal adds a new implicit tag argument of type <code class="sourceCode cpp">std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
to <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
and <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
that is incorporated into the existing overload resolution logic with a
higher priority than existing implicit parameters. To avoid conficts
with existing code, this parameter is placed as the first argument to
the operator, preceding the size or subject pointer. To avoid the
complexities of ADL, this proposal does not change any of the <em>name
lookup</em> rules associated to <em>new</em> and <em>delete</em>
expressions: it only changes the overload resolution that happens once a
name has been found.</p>
<p>For the declaration of a type-aware [de]allocation operator to be
valid, we explicitly require that the parameter be a (potentially
dependent) specialization of <code class="sourceCode cpp">std<span class="op">::</span>type_identity</code>,
but not a fully dependent type. In other words, the compiler must be
able to tell that the first parameter is of the form <code class="sourceCode cpp">std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
at the time of parsing the declaration, but before the declaration has
been instantiated in the case of a template. This is analogous to the
current behavior where we require specific concrete types in the
parameter list even in dependent contexts.</p>
<p>Once a set of candidate declarations has been found we perform the
same prioritized overload resolution steps, only with the addition of
<code class="sourceCode cpp">std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span></code>,
with a higher priority than the existing size and alignment parameters.
For illustration, here is how overload resolution changes
(<code class="sourceCode cpp">NEW</code> is the set of candidates found
by name lookup for <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>,
and <code class="sourceCode cpp">DELETE</code> is the equivalent for
<code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>).</p>
<p>If the user writes <code class="sourceCode cpp"><span class="kw">new</span> T<span class="op">(...)</span></code>,
the compiler checks (in order):</p>
<!-- # TODO: add aligned lookup of unaligned aligned types -->
<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">// T not overaligned</span></span>
<span id="cb5-2"><a href="#cb5-2" 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></span>
<span id="cb5-3"><a href="#cb5-3" 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>, 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>

</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">// T not overaligned</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>NEW<span class="op">(</span>type_identity<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></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>NEW<span class="op">(</span>type_identity<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>, align_val_t<span class="op">{</span><span class="kw">alignof</span><span class="op">(</span>T<span class="op">)})</span></span>
<span id="cb6-4"><a href="#cb6-4" 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></span>
<span id="cb6-5"><a href="#cb6-5" 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>, 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>

</div></td>
</tr>
<tr class="even">
<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">// T overaligned</span></span>
<span id="cb7-2"><a href="#cb7-2" 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>, align_val_t<span class="op">{</span><span class="kw">alignof</span><span class="op">(</span>T<span class="op">)})</span></span>
<span id="cb7-3"><a href="#cb7-3" 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></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">// T overaligned</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>NEW<span class="op">(</span>type_identity<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>, align_val_t<span class="op">{</span><span class="kw">alignof</span><span class="op">(</span>T<span class="op">)})</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>NEW<span class="op">(</span>type_identity<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></span>
<span id="cb8-4"><a href="#cb8-4" 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>, align_val_t<span class="op">{</span><span class="kw">alignof</span><span class="op">(</span>T<span class="op">)})</span></span>
<span id="cb8-5"><a href="#cb8-5" 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></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>If the user writes
<code class="sourceCode cpp"><span class="kw">delete</span> ptr</code>,
the compiler checks (in order):</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="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="co">// T not overaligned</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span>T<span class="op">-</span><span class="kw">or</span><span class="op">-</span>Base<span class="op">*</span>, destroying_delete_t<span class="op">{}</span>, <span class="op">...)</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">((</span><span class="dt">void</span><span class="op">*)</span>ptr, <span class="kw">sizeof</span><span class="op">(*</span>ptr<span class="op">))</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>DELETE<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="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="co">// T not overaligned</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span>T<span class="op">-</span><span class="kw">or</span><span class="op">-</span>Base<span class="op">*</span>, destroying_delete_t<span class="op">{}</span>, <span class="op">...)</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;{}</span>, <span class="op">(</span><span class="dt">void</span><span class="op">*)</span>ptr, <span class="kw">sizeof</span><span class="op">(</span>T<span class="op">))</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;{}</span>, <span class="op">(</span><span class="dt">void</span><span class="op">*)</span>ptr<span class="op">)</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">((</span><span class="dt">void</span><span class="op">*)</span>ptr, <span class="kw">sizeof</span><span class="op">(</span>T<span class="op">))</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>DELETE<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>
<tr class="even">
<td><div>

<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="co">// T overaligned</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span>T<span class="op">-</span><span class="kw">or</span><span class="op">-</span>Base<span class="op">*</span>, destroying_delete_t<span class="op">{}</span>, <span class="op">...)</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">((</span><span class="dt">void</span><span class="op">*)</span>ptr, <span class="kw">sizeof</span><span class="op">(</span>T<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="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">((</span><span class="dt">void</span><span class="op">*)</span>ptr, align_val_t<span class="op">{</span><span class="kw">alignof</span><span class="op">(</span>T<span class="op">)})</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>DELETE<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="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="co">// T overaligned</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span>T<span class="op">-</span><span class="kw">or</span><span class="op">-</span>Base<span class="op">*</span>, destroying_delete_t<span class="op">{}</span>, <span class="op">...)</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;{}</span>, <span class="op">(</span><span class="dt">void</span><span class="op">*)</span>ptr, <span class="kw">sizeof</span><span class="op">(</span>T<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="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;{}</span>, <span class="op">(</span><span class="dt">void</span><span class="op">*)</span>ptr, align_val_t<span class="op">{</span><span class="kw">alignof</span><span class="op">(</span>T<span class="op">)})</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">(</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;{}</span>, <span class="op">(</span><span class="dt">void</span><span class="op">*)</span>ptr<span class="op">)</span></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">((</span><span class="dt">void</span><span class="op">*)</span>ptr, <span class="kw">sizeof</span><span class="op">(</span>T<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="cb12-7"><a href="#cb12-7" aria-hidden="true" tabindex="-1"></a>DELETE<span class="op">((</span><span class="dt">void</span><span class="op">*)</span>ptr, align_val_t<span class="op">{</span><span class="kw">alignof</span><span class="op">(</span>T<span class="op">)})</span></span>
<span id="cb12-8"><a href="#cb12-8" aria-hidden="true" tabindex="-1"></a>DELETE<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>
<p>If multiple candidates match a given set of parameters, candidate
prioritisation and selection is performed according to usual rules for
overload resolution.</p>
<p>When a constructor throws an exception, a call to <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
is made to clean up. Overload resolution for this call remains
essentially the same, the only difference being that the selected <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
must have the same type-awareness as the preceding <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
or the program is considered ill-formed.</p>
<p>For clarity, in types with virtual destructors, <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
is resolved using the destructor’s class as the type being deallocated
(this matches the existing semantics of being equivalent to performing
<code class="sourceCode cpp"><span class="kw">delete</span> <span class="kw">this</span></code>
in the context of the class’s non virtual destructor).</p>
<h2 data-number="5.1" id="free-function-example"><span class="header-section-number">5.1</span> Free function example<a href="#free-function-example" class="self-link"></a></h2>
<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="kw">struct</span> SingleClass <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> UnrelatedClass <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> BaseClass <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> SubClass1 <span class="op">:</span> BaseClass <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> SubClass2 <span class="op">:</span> BaseClass <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> SubClass3 <span class="op">:</span> BaseClass <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb13-7"><a href="#cb13-7" 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>type_identity<span class="op">&lt;</span>SingleClass<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>; <span class="co">// (1)</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</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>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>; <span class="co">// (2)</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>derived_from<span class="op">&lt;</span>BaseClass<span class="op">&gt;</span> T<span class="op">&gt;</span></span>
<span id="cb13-11"><a href="#cb13-11" 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>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>; <span class="co">// (3)</span></span>
<span id="cb13-12"><a href="#cb13-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>type_identity<span class="op">&lt;</span>SubClass2<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>; <span class="co">// (4)</span></span>
<span id="cb13-13"><a href="#cb13-13" 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>type_identity<span class="op">&lt;</span>SubClass3<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span> <span class="op">=</span> <span class="kw">delete</span>; <span class="co">// (5)</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> SubClass4 <span class="op">:</span> BaseClass <span class="op">{</span></span>
<span id="cb13-16"><a href="#cb13-16" 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><span class="dt">size_t</span><span class="op">)</span>; <span class="co">// (6)</span></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">()</span> <span class="op">{</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> SingleClass<span class="op">()</span>;     <span class="co">// calls (1)</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> UnrelatedClass<span class="op">()</span>;  <span class="co">// calls (2)</span></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> BaseClass<span class="op">()</span>;       <span class="co">// calls (3) with T=BaseClass</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> SubClass1<span class="op">()</span>;       <span class="co">// calls (3) with T=SubClass1</span></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> SubClass2<span class="op">()</span>;       <span class="co">// calls (4)</span></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> SubClass3<span class="op">()</span>;       <span class="co">// resolves (5) reports error due to deleted operator</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> SubClass4<span class="op">()</span>;       <span class="co">// calls (6) as the class scoped operator wins</span></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> <span class="dt">int</span><span class="op">()</span>;             <span class="co">// calls (2) with T=int</span></span>
<span id="cb13-28"><a href="#cb13-28" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><span class="note"><span>[ <em>Note:</em> </span>The above is for
illustrative purposes only: it is a bad idea to provide a fully
unconstrained type-aware <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>.<span>
— <em>end note</em> ]</span></span></p>
<h2 data-number="5.2" id="in-class-example"><span class="header-section-number">5.2</span> In-class example<a href="#in-class-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="co">// In-class operator</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> SubClass1;</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> BaseClass <span class="op">{</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb14-5"><a href="#cb14-5" 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>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>; <span class="co">// (1)</span></span>
<span id="cb14-6"><a href="#cb14-6" 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>type_identity<span class="op">&lt;</span>SubClass1<span class="op">&gt;</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-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> SubClass1 <span class="op">:</span> BaseClass <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> SubClass2 <span class="op">:</span> BaseClass <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> SubClass3 <span class="op">:</span> BaseClass <span class="op">{</span></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 class="op">}</span>;</span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> SubClass4 <span class="op">:</span> BaseClass <span class="op">{</span></span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span></span>
<span id="cb14-16"><a href="#cb14-16" 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>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>; <span class="co">// (4)</span></span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb14-18"><a href="#cb14-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-19"><a href="#cb14-19" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">()</span> <span class="op">{</span></span>
<span id="cb14-20"><a href="#cb14-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> BaseClass;         <span class="co">// calls (1) with T=BaseClass</span></span>
<span id="cb14-21"><a href="#cb14-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> SubClass1<span class="op">()</span>;       <span class="co">// calls (2)</span></span>
<span id="cb14-22"><a href="#cb14-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> SubClass2<span class="op">()</span>;       <span class="co">// calls (1) with T=SubClass2</span></span>
<span id="cb14-23"><a href="#cb14-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> SubClass3<span class="op">()</span>;       <span class="co">// calls (3)</span></span>
<span id="cb14-24"><a href="#cb14-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">new</span> SubClass4<span class="op">()</span>;       <span class="co">// calls (4) with T=SubClass4</span></span>
<span id="cb14-25"><a href="#cb14-25" aria-hidden="true" tabindex="-1"></a>  <span class="op">::</span><span class="kw">new</span> BaseClass<span class="op">()</span>;     <span class="co">// ignores in-class operators and uses appropriate global operator</span></span>
<span id="cb14-26"><a href="#cb14-26" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 data-number="5.3" id="operator-suppression-example"><span class="header-section-number">5.3</span> Operator suppression example<a href="#operator-suppression-example" class="self-link"></a></h2>
<p>There are many cases where projects may not want types to be
allocated and deallocated via
<code class="sourceCode cpp"><span class="kw">new</span></code> and
<code class="sourceCode cpp"><span class="kw">delete</span></code>
operators. Doing so today requires injecting operators into the relevant
types, which often results in extensive use of macros. This proposal
allows constraint based selection of target types, and as such can be
leveraged to specify deleted operators, and so automatically prevent
their use e.g.</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">concept</span> SelectionConstraint <span class="op">=</span> <span class="op">...</span>;</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>SelectionConstraint T<span class="op">&gt;</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>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span> <span class="op">=</span> <span class="kw">delete</span>;</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="op">...</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>SelectionConstraint T<span class="op">&gt;</span> <span class="dt">void</span> <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 class="op">=</span> <span class="kw">delete</span>;</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a><span class="op">...</span></span></code></pre></div>
<h2 data-number="5.4" id="template-type-allocation-example"><span class="header-section-number">5.4</span> Template type allocation
example<a href="#template-type-allocation-example" class="self-link"></a></h2>
<p>The template arguments to a type aware operator new or delete are not
required to be directly applied to <code class="sourceCode cpp">std<span class="op">::</span>type_identity</code>,
but are simply available for usual template deduction, so a type aware
allocation function can be defined to operate over a template type,
e.g.</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">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">int</span> N<span class="op">&gt;</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> MyArrayType <span class="op">{</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">typename</span> T, <span class="dt">int</span> N<span class="op">&gt;</span></span>
<span id="cb16-6"><a href="#cb16-6" 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>type_identity<span class="op">&lt;</span>MyArrayType<span class="op">&lt;</span>T, N<span class="op">&gt;&gt;</span>, <span class="dt">size_t</span>, <span class="op">...)</span> <span class="op">{</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a> <span class="op">...</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a><span class="op">...</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a><span class="co">// calls the above operator new&lt;int, 5&gt;(std::type_identity&lt;MyArrayType&lt;int, 5&gt;&gt;, ...)</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> A <span class="op">=</span> <span class="kw">new</span> MyArrayType<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">5</span><span class="op">&gt;</span>;</span></code></pre></div>
<h1 data-number="6" id="proposed-wording"><span class="header-section-number">6</span> Proposed wording<a href="#proposed-wording" class="self-link"></a></h1>
<h2 data-number="6.1" id="cpp.predefined"><span class="header-section-number">6.1</span> <span><a href="https://wg21.link/cpp.predefined">[cpp.predefined]</a></span><a href="#cpp.predefined" class="self-link"></a></h2>
<p>Update <span><a href="https://wg21.link/tab:cpp.predefined.ft">[tab:cpp.predefined.ft]</a></span>
to include a feature detection macro
<code class="sourceCode cpp">__cpp_typed_allocation</code> with a
release appropriate value.</p>
<h2 data-number="6.2" id="basic.stc.dynamic.allocation"><span class="header-section-number">6.2</span> <span><a href="https://wg21.link/basic.stc.dynamic.allocation">[basic.stc.dynamic.allocation]</a></span><a href="#basic.stc.dynamic.allocation" class="self-link"></a></h2>
<p>Updates for <span><a href="https://wg21.link/basic.stc.dynamic.allocation">[basic.stc.dynamic.allocation]</a></span></p>
<p><span class="draftnote" style="color: #0000ff">[ Drafting note: The
wording changes here are intended to provide for the existence of a
correct <code class="sourceCode default">operator new</code> or
<code class="sourceCode default">operator new[]</code> in which the
first parameter is a
<code class="sourceCode default">std::type_identity&lt;T&gt;</code> tag
parameter where previously the first parameter was required to be of
type <code class="sourceCode default">std::size_t</code>. The language
is intended to further permit this tag parameter to be a dependent type,
as long as it is always a specialization of
<code class="sourceCode default">std::type_identity</code>, e.g <code class="sourceCode default">template &lt;typename T&gt; void *operator new(T, std::size_t)</code>
would always be invalid, even if
<code class="sourceCode default">T</code> was
<code class="sourceCode default">std::type_identity&lt;E&gt;</code> for
some <code class="sourceCode default">E</code>, or similarly <code class="sourceCode default">template &lt;template&lt;class&gt; class T&gt; void *operator new(T&lt;int&gt;, std::size_t)</code>.
]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
An allocation function <span class="add" style="color: #006e28"><ins>or
allocation function template</ins></span><span class="rm" style="color: #bf0303"><del>that is not a class member
function</del></span> shall <span class="add" style="color: #006e28"><ins>either</ins></span> belong to the global
scope and not have a name with internal linkage <span class="add" style="color: #006e28"><ins>or be a class member function</ins></span>.
The <span class="add" style="color: #006e28"><ins>declared</ins></span>
return type shall be <span class="add" style="color: #006e28"><ins>the
non-dependent type</ins></span> <code class="sourceCode cpp"><span class="dt">void</span><span class="op">*</span></code>.
<span class="add" style="color: #006e28"><ins>A non-template allocation
function shall have at least one parameter, and an allocation function
template shall have at least two parameters. If the first parameter is
of type
<span><code class="sourceCode default">std::type_identity&lt;T&gt;</code></span>
for some type <span><code class="sourceCode default">T</code></span>
there shall be at least two parameters; the first parameter is called
the <em>type-identity parameter</em>, and the second parameter is called
the <em>size parameter</em>. Otherwise, the first parameter is called
the <em>size parameter</em>.</ins></span> The <span class="rm" style="color: #bf0303"><del>first</del></span> <span class="add" style="color: #006e28"><ins>size</ins></span> parameter shall have <span class="add" style="color: #006e28"><ins>the non-dependent</ins></span>
type <code class="sourceCode cpp">std<span class="op">::</span><span class="dt">size_t</span></code>
(<span><a href="https://wg21.link/support.types">[support.types]</a></span>).
<span class="rm" style="color: #bf0303"><del>The first parameter shall
not</del></span> <span class="add" style="color: #006e28"><ins>Neither
the type-identity parameter, if present, nor the size parameter
shall</ins></span> have an associated default argument (<span><a href="https://wg21.link/dcl.fct.default">[dcl.fct.default]</a></span>).
<span class="add" style="color: #006e28"><ins>The type-identity
parameter represents the type being allocated, such that when allocating
an object or array of type
<span><code class="sourceCode default">T</code></span>, the
type-identity parameter shall be of type
<span><code class="sourceCode default">std::type_identity&lt;U&gt;</code></span>
where <span><code class="sourceCode default">U</code></span> is the type
<span><code class="sourceCode default">T</code></span> with qualifiers
removed.</ins></span> The value of the <span class="rm" style="color: #bf0303"><del>first</del></span><span class="add" style="color: #006e28"><ins>size</ins></span> parameter is interpreted
as the requested size of the allocation. <span class="rm" style="color: #bf0303"><del>An allocation function can be a function
template. Such a template shall declare its return type and first
parameter as specified above (that is, template parameter types shall
not be used in the return type and first parameter type). Allocation
function templates shall have two or more parameters.</del></span></p>
</blockquote>
<h2 data-number="6.3" id="basic.stc.dynamic.deallocation"><span class="header-section-number">6.3</span> <span><a href="https://wg21.link/basic.stc.dynamic.deallocation">[basic.stc.dynamic.deallocation]</a></span><a href="#basic.stc.dynamic.deallocation" class="self-link"></a></h2>
<p>Updates for <span><a href="https://wg21.link/basic.stc.dynamic.deallocation">[basic.stc.dynamic.deallocation]</a></span></p>
<p><span class="draftnote" style="color: #0000ff">[ Drafting note: As
with the changes to <span><a href="https://wg21.link/basic.stc.dynamic.allocation">[basic.stc.dynamic.allocation]</a></span>
the intent of this wording is to permit the first parameter to be a
<code class="sourceCode default">std::type_identity</code>
specialization as long as we can identify this as a specialization of
<code class="sourceCode default">std::type_identity</code> prior to any
template instantiation. ]</span></p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>Each
deallocation function shall return
<code class="sourceCode cpp"><span class="dt">void</span></code>. <span class="add" style="color: #006e28"><ins>A deallocation function shall
have at least one parameter. If the first parameter is of type
<span><code class="sourceCode default">std::type_identity&lt;T&gt;</code></span>
for some type <span><code class="sourceCode default">T</code></span>,
there shall be at least two parameters; the first parameter is called
the <em>type-identity parameter</em>, the second parameter is called the
<em>address parameter</em>. Otherwise, the first parameter is called the
<em>address parameter</em>. If the function has a type-identity
parameter, it is not a destroying delete and the third parameter, if
present, shall not be of type
<span><code class="sourceCode default">std::destroying_delete_t</code></span>.</ins></span>
If the function is a destroying operator delete declared in class type
C, the type of its <span class="rm" style="color: #bf0303"><del>first</del></span><span class="add" style="color: #006e28"><ins>address</ins></span> parameter shall be
<code class="sourceCode cpp">C<span class="op">*</span></code>;
otherwise, the type of its <span class="rm" style="color: #bf0303"><del>first</del></span><span class="add" style="color: #006e28"><ins>address</ins></span> parameter shall be
<code class="sourceCode cpp"><span class="dt">void</span><span class="op">*</span></code>.
A deallocation function may have <span class="rm" style="color: #bf0303"><del>more than one parameter</del></span><span class="add" style="color: #006e28"><ins>additional parameters beyond the
type-identity and address parameters</ins></span>. A <em>usual
deallocation function</em> is a deallocation function whose parameters
after the <span class="rm" style="color: #bf0303"><del>first</del></span><span class="add" style="color: #006e28"><ins>address parameter</ins></span> are</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(3.1)</a></span>optionally,
a parameter of type <code class="sourceCode cpp">std<span class="op">::</span>destroying_delete_t</code>,
then</li>
<li><span class="marginalizedparent"><a class="marginalized">(3.2)</a></span>optionally,
a parameter of type <code class="sourceCode cpp">std<span class="op">::</span><span class="dt">size_t</span></code>,
then</li>
<li><span class="marginalizedparent"><a class="marginalized">(3.3)</a></span>optionally,
a parameter of type <code class="sourceCode cpp">std<span class="op">::</span>align_val_t</code>.</li>
</ul>
<p>A destroying operator delete shall be a usual deallocation function.
A deallocation function may be <span class="rm" style="color: #bf0303"><del>an instance of a function
template</del></span><span class="add" style="color: #006e28"><ins>templated</ins></span>. Neither the <span class="rm" style="color: #bf0303"><del>first</del></span><span class="add" style="color: #006e28"><ins>address</ins></span> parameter
nor the return type shall depend on a template parameter. A deallocation
function <span class="rm" style="color: #bf0303"><del>template shall
have two or more function parameters</del></span> <span class="add" style="color: #006e28"><ins>can be a function template. Such a function
template shall have at least two parameters, and declare its address
parameter as specified above</ins></span>. A template instance <span class="rm" style="color: #bf0303"><del>is never a usual deallocation
function, regardless of its signature.</del></span><span class="add" style="color: #006e28"><ins>is only a usual deallocation function if it
has a type-identity parameter, and the type-identity parameter is a
dependent type (i.e. the type-identity parameter may be of type
<span><code class="sourceCode default">std::type_identity&lt;T&gt;</code></span>
where <span><code class="sourceCode default">T</code></span> shall be a
dependent type), and the type-identity parameter is the only dependent
parameter.</ins></span></p>
</blockquote>
<div class="draftnote" style="color: #0000ff">
<p>[ Drafting note: Is this sufficient to prevent a case like this from
being a usual deallocation function? It seems like it might not cover
Args being an empty pack?</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>template &lt;typename T, typename... Args&gt;</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>void operator delete(type_identity&lt;T&gt;, void*, Args...);</span></code></pre></div>
]

</div>
<h2 data-number="6.4" id="expr.new"><span class="header-section-number">6.4</span> <span><a href="https://wg21.link/expr.new">[expr.new]</a></span><a href="#expr.new" class="self-link"></a></h2>
<p>Updates to <span><a href="https://wg21.link/expr.new">[expr.new]</a></span></p>
<div class="draftnote" style="color: #0000ff">
<p>[ Drafting note: We are adding a new implicit tag parameter to the
head of the argument list, we’re calling this tag parameter the
type-identity. It is a
<code class="sourceCode default">std::type_identity&lt;&gt;</code> over
the qualifier-free allocated type
<code class="sourceCode default">T</code> for an allocation of the form
<code class="sourceCode default">new T</code> or
<code class="sourceCode default">new T[&lt;expr&gt;]</code>. This is the
method by which the allocated type is exposed to developers.</p>
<p>We are extending the overload resolution steps to include this new
parameter. The intent is for the type aware overloads to get priority
over any other “matching” option. e.g a type aware operator new without
<code class="sourceCode default">align_val_t</code> will still get
priority over a viable
<code class="sourceCode default">align_val_t</code> candidate (on the
principle that the allocator can query the allocated type alignment
directly). This requires indenting and adding paragraph numbers to steps
in paragraph 20. The below removal is the section of text that is being
inset and separated into steps below. ]</p>
</div>
<div class="rm" style="color: #bf0303">

<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">20</a></span>
Overload resolution is performed on a function call created by
assembling an argument list. The first argument is the amount of space
requested, and has type
<code class="sourceCode default">std::size_t</code>. If the type of the
allocated object has new-extended alignment, the next argument is the
type’s alignment, and has type
<code class="sourceCode default">std::align_val_t</code>. If the
new-placement syntax is used, the initializer-clauses in its
expression-list are the succeeding arguments. If no matching function is
found then</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(20.1)</a></span> if
the allocated object type has new-extended alignment, the alignment
argument is removed from the argument list;</li>
<li><span class="marginalizedparent"><a class="marginalized">(20.2)</a></span>
otherwise, an argument that is the type’s alignment and has type
<code class="sourceCode default">std::align_val_t</code> is added into
the argument list immediately after the first argument;</li>
</ul>
<p>and then overload resolution is performed again.</p>
</blockquote>

</div>
<div class="add" style="color: #006e28">

<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">20</a></span> The
<em>type-identity argument</em> is a value of type
<code class="sourceCode default">std::type_identity&lt;U&gt;</code>.
When the allocated type is “array of N T”, or the type
<code class="sourceCode default">T</code> otherwise,
<code class="sourceCode default">U</code> is the type
<code class="sourceCode default">T</code> with qualifiers removed.</p>
</blockquote>

</div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">21</a></span>
Overload resolution is performed on a function call by assembling an
argument list.</p>
</blockquote>
<p><span class="draftnote" style="color: #0000ff">[ Drafting note: some
of these points exist, but are being inset and put into a sub-list
]</span></p>
<blockquote>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(21.1)</a></span>
<span class="add" style="color: #006e28"><ins>The first argument is the
type-identity argument, the second</ins></span><span class="rm" style="color: #bf0303"><del>The first</del></span> argument is the
amount of space requested, and has type <code class="sourceCode cpp">std<span class="op">::</span><span class="dt">size_t</span></code>.</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(21.2)</a></span> If
the type of the allocated object has new-extended alignment, the next
argument is the type’s alignment, and has type <code class="sourceCode cpp">std<span class="op">::</span>align_val_t</code>.
If the new-placement syntax is used, the initializer-clauses in its
expression-list are the succeeding arguments. If no matching function is
found then</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(21.2.1)</a></span>
if the allocated object type has new-extended alignment, the alignment
argument is removed from the argument list;</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(21.2.2)</a></span>
otherwise, an argument that is the type’s alignment and has type <code class="sourceCode cpp">std<span class="op">::</span>align_val_t</code>
is added into the argument list immediately after the size
argument;</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(21.2.3)</a></span>
and then overload resolution is performed again.</p></li>
</ul></li>
</ul>
</blockquote>
<div class="add" style="color: #006e28">

<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(21.3)</a></span> If
no matching function was found and the type-identity argument was
present in the argument list, the above overload resolution steps are
repeated without the type-identity argument.</li>
</ul>
</blockquote>

</div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">29</a></span> A
declaration of a placement deallocation function matches the declaration
of a placement allocation function if it has the same number of
parameters and, after parameter transformations (<span><a href="https://wg21.link/dcl.fct">[dcl.fct]</a></span>), all parameter
types except <span class="rm" style="color: #bf0303"><del>the
first</del></span><span class="add" style="color: #006e28"><ins>the size
and object</ins></span> are identical.</p>
</blockquote>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">30</a></span> If a
new-expression calls a deallocation function it passes <span class="add" style="color: #006e28"><ins>the type-identity argument as the first
argument if it was passed to the allocation function, and</ins></span>
the value returned from the allocation function call as the <span class="rm" style="color: #bf0303"><del>first argument</del></span><span class="add" style="color: #006e28"><ins>argument for the address
parameter</ins></span> of type <code class="sourceCode cpp"><span class="dt">void</span> <span class="op">*</span></code>.</p>
</blockquote>
<h2 data-number="6.5" id="expr.delete"><span class="header-section-number">6.5</span> <span><a href="https://wg21.link/expr.delete">[expr.delete]</a></span><a href="#expr.delete" class="self-link"></a></h2>
<div class="add" style="color: #006e28">

<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
For an delete operator applied to an operand of type
<code class="sourceCode default">T*</code>, <em>type-identity
argument</em> is a value of type
<code class="sourceCode default">std::type_identity&lt;U&gt;</code>
where <code class="sourceCode default">U</code> is the result of
removing qualifiers from the type
<code class="sourceCode default">T</code>.</p>
</blockquote>

</div>
<div class="draftnote" style="color: #0000ff">
<p>[ Drafting note: p10 below is trying to update the existing overload
resolution semantics to say</p>
<ul>
<li><p>Perform template argument deduction and synthesis - this
previously was not performed as it was definitionally not
possible.</p></li>
<li><p>Specify selection of the best viable function given that it is
now possible for multiple allocation functions of the same type to
exist.</p></li>
</ul>
]

</div>
<div class="add" style="color: #006e28">

<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">10</a></span> For
each function template found, function template argument deduction
(<span><a href="https://wg21.link/temp.deduct">[temp.deduct]</a></span>)
is performed using the type of the type-identity as the first parameter,
and the type of each subsequent parameter in the candidate function
template. If argument deduction and checking succeeds, and the deduced
type of the first parameter is the same type as the type identity tag,
the deduced template-arguments are used to synthesize the declaration of
a single function template specialization; Otherwise the declaration is
eliminated from further consideration.</p>
</blockquote>

</div>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">11</a></span>The
deallocation function to be called is selected <span class="add" style="color: #006e28"><ins>from the candidate set</ins></span> as
follows:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(11.1)</a></span> If
any of the deallocation functions is a destroying operator delete, all
deallocation functions that are not destroying operator deletes are
eliminated from further consideration.</li>
</ul>
</blockquote>
<div class="add" style="color: #006e28">

<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(11.2)</a></span> If
any of the deallocation functions have a first parameter of the same
type as the type-identity, all deallocation functions that do not have a
first parameter of that type are eliminated from further
consideration.</li>
</ul>
</blockquote>

</div>
<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(11.3)</a></span> If
the type has new-extended alignment, a function with a parameter of type
std::align_val_t is preferred; otherwise a function without such a
parameter is preferred. If any preferred functions are found, all
non-preferred functions are eliminated from further consideration.</li>
</ul>
</blockquote>
<div class="add" style="color: #006e28">

<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(11.4)</a></span> If
multiple functions of the same type are found, only the most viable
functions <span><a href="https://wg21.link/over.match.best">[over.match.best]</a></span>
are retained, all others are eliminated from further consideration.</li>
</ul>
</blockquote>

</div>
<blockquote>
<p>…</p>
<p><span class="marginalizedparent"><a class="marginalized">12</a></span> For a
single-object delete expression, the deleted object is the object A
pointed to by the operand if the static type of A does not have a
virtual destructor, and the most-derived object of A otherwise. <span class="note"><span>[ <em>Note:</em> </span>If the deallocation function
is not a destroying operator delete and the deleted object is not the
most derived object in the former case, the behavior is undefined, as
stated above.<span> — <em>end note</em> ]</span></span> <span class="add" style="color: #006e28"><ins>If the selected function is type
aware, then it will be called with the type-identity argument as the
first argument to the call</ins></span>. For an array delete expression,
the deleted object is the array object. When a delete-expression is
executed, the selected deallocation function shall be called with the
address of the deleted object in a single-object delete expression, or
the address of the deleted object suitably adjusted for the array
allocation overhead ([expr.new]) in an array delete expression, as <span class="add" style="color: #006e28"><ins>the</ins></span><span class="rm" style="color: #bf0303"><del>its</del></span> first argument <span class="add" style="color: #006e28"><ins>following the type identity
argument if present</ins></span>.</p>
</blockquote>
<h2 data-number="6.6" id="expr.const"><span class="header-section-number">6.6</span> <span><a href="https://wg21.link/expr.const">[expr.const]</a></span><a href="#expr.const" class="self-link"></a></h2>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">(10.18.1)</a></span>
the selected allocation function is a replaceable global allocation
function (<span><a href="https://wg21.link/new.delete.single">[new.delete.single]</a></span>,
<span><a href="https://wg21.link/new.delete.array">[new.delete.array]</a></span>)
<span class="add" style="color: #006e28"><ins>or a global type aware
allocation function where, if the the type identity tag is ignored,
matches a replaceable global allocation function</ins></span> and the
allocated storage is deallocated within the evaluation of E, or</p>
</blockquote>
<h1 data-number="7" id="design-choices-and-notes"><span class="header-section-number">7</span> Design choices and notes<a href="#design-choices-and-notes" class="self-link"></a></h1>
<h2 data-number="7.1" id="design-choice-allowing-type-aware-allocation-functions-in-constant-expressions"><span class="header-section-number">7.1</span> Design choice: Allowing type
aware allocation functions in constant expressions<a href="#design-choice-allowing-type-aware-allocation-functions-in-constant-expressions" class="self-link"></a></h2>
<p><strong>New since Wroclaw</strong></p>
<p>In the current specification it is not possible for an author to
specify a constexpr <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
or <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>.
Instead, using a <em>new-expression</em> or a <em>delete-expression</em>
in a
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
context requires that the resolved operator be <code class="sourceCode cpp"><span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>
/ <code class="sourceCode cpp"><span class="op">::</span><span class="kw">operator</span> <span class="kw">delete</span></code>,
and the compiler elides the call entirely. In particular, if an in-class
<code class="sourceCode cpp">T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>
is defined and the <em>new-expression</em> resolves to it, the
<em>new-expression</em> is not
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>-friendly.
That seems to be an arbitrary limitation.</p>
<p>We clearly don’t want or need such a limitation for typed <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>.
Our solution to that is to treat a global typed <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
(without placement parameters) just like an untyped <code class="sourceCode cpp"><span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>,
i.e. as a <em>replaceable global allocation function</em>. While that
does mean the compiler will assume the behaviour of typed <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>,
that seems like a reasonable assumption inside
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>.
We apply the same rationale to <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span><span class="op">[]</span></code>,
<code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>,
and <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span><span class="op">[]</span></code>
in order to fully support type aware allocators where existing global
allocators are supported.</p>
<h2 data-number="7.2" id="design-choice-stripping-qualifiers-from-the-type"><span class="header-section-number">7.2</span> Design choice: Stripping
qualifiers from the type<a href="#design-choice-stripping-qualifiers-from-the-type" class="self-link"></a></h2>
<p><strong>New since Wroclaw</strong></p>
<p>There is a question as to whether the type-identity should include
qualifiers. In previous drafts this was not addressed, and retaining the
qualifiers was implied. After consideration we have realised that this
would be surprising, is inconsistent with how the type being allocated
is presented to the developer throughout the process of allocation and
deallocation, and results in the type-identity trivially diverging
between such allocation and deallocation e.g.</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">const</span> T <span class="op">*</span>t <span class="op">=</span> <span class="kw">new</span> T;</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="op">...</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="kw">delete</span> t;</span></code></pre></div>
<h2 data-number="7.3" id="design-choice-safety-restriction-on-mismatched-declaration-scopes"><span class="header-section-number">7.3</span> Design choice: Safety
restriction on mismatched declaration scopes<a href="#design-choice-safety-restriction-on-mismatched-declaration-scopes" class="self-link"></a></h2>
<p><strong>New since Wroclaw</strong></p>
<p>There is currently no language mechanism to enforce that <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
and <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
are defined as a pair. That is a potential source of confusion and bugs.
However, since we are introducing a new form of <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
and <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>,
we are free to change these rules, and it would be simple to do so. In
<span><a href="https://wg21.link/expr.new">[expr.new]</a></span> we
suggest adding the follow paragraph to force the selected <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
to be in the same scope as its matching <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>.
We believe that the vast majority of use cases will already assume
that’s the case, and this would only catch a potentially common
misuse.</p>
<div class="add" style="color: #006e28">

<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">31</a></span> If a
single matching deallocation is found and either the allocation function
or the deallocation function has a type-identity parameter, then both
functions shall belong to the same scope (<span><a href="https://wg21.link/basic.scope.scope">[basic.scope.scope]</a></span>),
otherwise the program is ill-formed.</p>
</blockquote>

</div>
<h2 data-number="7.4" id="design-choice-all-implicit-parameters-are-mandatory"><span class="header-section-number">7.4</span> Design choice: All implicit
parameters are mandatory<a href="#design-choice-all-implicit-parameters-are-mandatory" class="self-link"></a></h2>
<p><strong>New since Wroclaw</strong></p>
<p>The proposal currently continues to consider optional implicit
parameters to be optional. During edge case testing we found that the
non-universality of sized deallocation creates a hazard where a less
constrained sized deallocation may be selected over a more constrained
unsized deallocation function. We believe it is actually reasonable to
update the language to make all currently optional implicit parameters
mandatory for type aware allocators.</p>
<p>We believe this is a reasonable step to take, as in the future any
type-oriented implicit parameters can be based on the <code class="sourceCode cpp">std<span class="op">::</span>type_identity</code>
parameter, which would reduce the exponential increase in new allocation
and deallocation APIs.</p>
<p>In addition to resolving the hazard derived from compiler mode flag
changes this also simplifies lookup semantics for the operators, and
resolves the problem of sized deallocation for exception cleanup in the
context of type aware allocation and deallocation (P3492 addresses this
problem for environments where type aware allocation may not be an
option).</p>
<p>The following wording changes are necessary:</p>
<ul>
<li><p>In <span><a href="https://wg21.link/basic.stc.dynamic.allocation">[basic.stc.dynamic.allocation]</a></span>
paragraph 1 and <span><a href="https://wg21.link/basic.stc.dynamic.deallocation">[basic.stc.dynamic.deallocation]</a></span>
paragraph 3</p>
<div class="add" style="color: #006e28">

<blockquote>
<p>If a type identity parameter is provided, the otherwise optional
parameters are required to be present and specified with non-dependent
types.</p>
</blockquote>

</div></li>
<li><p><span><a href="https://wg21.link/expr.new">[expr.new]</a></span>
paragraph 29 is modified:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized">29</a></span> <span class="add" style="color: #006e28"><ins>A declaration of a type aware
placement deallocation function matches the declaration of a type aware
placement deallocation function if the types of each parameter after the
mandatory parameters are the same.</ins></span> Otherwise, a declaration
of a placement deallocation function matches the declaration of a
placement allocation function if it has the same number of parameters
and, after parameter transformations ([dcl.fct]). … <span class="marginalizedparent"><a class="marginalized">30</a></span> If a
new-expression calls a deallocation function, it passes the value
returned from the allocation function call as the argument of type <code class="sourceCode cpp"><span class="dt">void</span><span class="op">*</span></code>
<span class="add" style="color: #006e28"><ins>as the address
parameter</ins></span>. <span class="add" style="color: #006e28"><ins>If
the deallocation operator has a type identity parameter, the allocation
size is passed as the third parameter of type size_t.</ins></span>…</p>
</blockquote></li>
</ul>
<h2 data-number="7.5" id="design-choice-stdtype_identityt-vs-raw-template-argument"><span class="header-section-number">7.5</span> Design choice: <code class="sourceCode cpp">std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
vs “raw” template argument<a href="#design-choice-stdtype_identityt-vs-raw-template-argument" class="self-link"></a></h2>
<p>In an earlier draft, this paper was proposing the following
(seemingly simpler) mechanism. Instead of using <code class="sourceCode cpp">std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as a tag, the compiler would search as per the following expression:</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><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 passing the type being
allocated directly as a template argument instead of using a <code class="sourceCode cpp">std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
tag parameter. Unfortunately, this has a number of problems, the most
significant being that it’s not possible to distinguish the
newly-introduced type-aware operator from existing template <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
and <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
declarations.</p>
<p>For example, a valid <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
declaration today would be:</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">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="cb20-2"><a href="#cb20-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>, Args<span class="op">...)</span>;</span></code></pre></div>
<p>Hence, an expression like <code class="sourceCode cpp"><span class="kw">new</span> <span class="op">(</span><span class="dv">42</span><span class="op">)</span> <span class="dt">int</span><span class="op">(</span><span class="dv">3</span><span class="op">)</span></code>
which would result in a call like <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span><span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;(</span><span class="kw">sizeof</span><span class="op">(</span><span class="dt">int</span><span class="op">)</span>, <span class="dv">42</span><span class="op">)</span></code>
could result in this operator being called with a meaning that isn’t
clear – is it a type-aware (placement) operator or a type-unaware
placement operator? This also means that existing and legal operators
could start being called in code bases that don’t expect it, which is
problematic.</p>
<p>Beyond that being confusing for users, this also creates a legitimate
problem for the compiler since the resolution of new and delete
expressions is based on checking various forms of the operators using
different priorities. In order for this to make sense, the compiler has
to be able to know exactly what “category” of operator a declaration
falls in, so it can perform overload resolution at each priority on the
right candidates.</p>
<p>Finally, when a constructor in a <em>new-expression</em> throws an
exception, an <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
that must be a <em>usual deallocation function</em> gets called to clean
up. If there is no matching usual deallocation function, no cleanup is
performed. Using a template parameter instead of a tag argument could
lead to code where no cleanup happened to now find a valid usual
deallocation function and perform a cleanup.</p>
<p>Taken together we believe these issues warrant the use of an explicit
tag parameter.</p>
<h2 data-number="7.6" id="design-choice-stdtype_identityt-vs-t"><span class="header-section-number">7.6</span> Design choice: <code class="sourceCode cpp">std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
vs <code class="sourceCode cpp">T<span class="op">*</span></code><a href="#design-choice-stdtype_identityt-vs-t" class="self-link"></a></h2>
<p>This proposal uses <code class="sourceCode cpp">std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
as a tag argument rather than passing a first argument of type
<code class="sourceCode cpp">T<span class="op">*</span></code>. At first
sight, passing
<code class="sourceCode cpp">T<span class="op">*</span></code> as a
first tag argument seems to simplify the proposal and decouple the
compiler from the standard library.</p>
<p>However, this approach hides an array of subtle problems that are
avoided through the use of <code class="sourceCode cpp">std<span class="op">::</span>type_identity</code>.</p>
<h3 data-number="7.6.1" id="problems-with-the-value-being-passed"><span class="header-section-number">7.6.1</span> Problems with the value being
passed<a href="#problems-with-the-value-being-passed" class="self-link"></a></h3>
<p>The first problem is the value being passed as the tag parameter.
Given operator signatures of the form</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">&gt;</span> <span class="dt">void</span> <span class="op">*</span><span class="kw">operator</span> <span class="kw">new</span><span class="op">(</span>T<span class="op">*</span>, <span class="dt">size_t</span><span class="op">)</span>;</span>
<span id="cb21-2"><a href="#cb21-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 class="dt">void</span> <span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span>T<span class="op">*</span>, <span class="dt">void</span><span class="op">*)</span>;</span></code></pre></div>
<p>Under the hood, the compiler could perform calls like</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="co">// T* ptr = new T(...)</span></span>
<span id="cb22-2"><a href="#cb22-2" 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>T<span class="op">*)</span><span class="kw">nullptr</span>, <span class="kw">sizeof</span><span class="op">(</span>T<span class="op">))</span>;</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="co">// delete ptr</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">delete</span><span class="op">&lt;</span>T<span class="op">&gt;((</span>T<span class="op">*)</span><span class="kw">nullptr</span>, ptr<span class="op">)</span>;</span></code></pre></div>
<p>A developer could reasonably be assumed to know that the tag
parameter to <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
can’t be anything but a null pointer. However, for <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
we can be assured that people will be confused about receiving two
pointer parameters, where the explicitly typed parameter is
<code class="sourceCode cpp"><span class="kw">nullptr</span></code>.
Also note that we cannot pass the object pointer through that parameter
as <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
is called after the object has been destroyed. Passing the memory to be
deallocated through a typed pointer is an incitation to use that memory
as a <code class="sourceCode cpp">T</code> object, which would be
undefined behavior.</p>
<h3 data-number="7.6.2" id="silent-conversions-to-base-types"><span class="header-section-number">7.6.2</span> Silent conversions to base
types<a href="#silent-conversions-to-base-types" class="self-link"></a></h3>
<p>A scenario we have discussed is developers wishing to provide custom
[de]allocation operators for a whole class hierarchy. When using a typed
pointer as the tag, this would be written as:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Base <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb23-2"><a href="#cb23-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>Base<span class="op">*</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>;</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <span class="kw">operator</span> <span class="kw">delete</span><span class="op">(</span>Base<span class="op">*</span>, <span class="dt">void</span><span class="op">*)</span>;</span></code></pre></div>
<p>This operator would then also match any derived types of
<code class="sourceCode cpp">Base</code>, which may or may not be
intended. If not intended, the conversion from
<code class="sourceCode cpp">Derived<span class="op">*</span></code> to
<code class="sourceCode cpp">Base<span class="op">*</span></code> would
be entirely silent and may not be noticed. Furthermore, this would
basically defeat the purpose of providing type knowledge to the
allocator, since only the type of the base class would be known. We
believe that the correct way of implementing an operator for a hierarchy
is this:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Base <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-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="cb24-3"><a href="#cb24-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>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>; <span class="co">// T is the actual type being allocated</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-5"><a href="#cb24-5" 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="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <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="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Or alternatively, in the global namespace:</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>derived_from<span class="op">&lt;</span>Base<span class="op">&gt;</span> T<span class="op">&gt;</span></span>
<span id="cb25-2"><a href="#cb25-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>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>;</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span>std<span class="op">::</span>derived_from<span class="op">&lt;</span>Base<span class="op">&gt;</span> T<span class="op">&gt;</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> <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></code></pre></div>
<p>For these reasons, we believe that a tag type like <code class="sourceCode cpp">std<span class="op">::</span>type_identity</code>
is the right design choice.</p>
<h2 data-number="7.7" id="design-choice-location-of-stdtype_identityt"><span class="header-section-number">7.7</span> Design choice: Location of
<code class="sourceCode cpp">std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span></code><a href="#design-choice-location-of-stdtype_identityt" class="self-link"></a></h2>
<p>When writing this paper, we went back and forth of the order of
arguments. This version of the paper proposes:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-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="cb26-2"><a href="#cb26-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="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-4"><a href="#cb26-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="cb26-5"><a href="#cb26-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="cb26-6"><a href="#cb26-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>Another approach would be:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-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="cb27-2"><a href="#cb27-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="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb27-4"><a href="#cb27-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="cb27-5"><a href="#cb27-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="cb27-6"><a href="#cb27-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>The existing specification allows for the existence of template
(including variadic template) declarations of operator new and delete,
and this functionality is used in existing code bases. This leads to
problems compiling real world code where overload resolution will allow
selection of a non-SFINAE-safe declaration and subsequently break during
compilation.</p>
<p>Placing the tag argument first ensures that no existing operator
definition can match, and so we are guaranteed to be free from
conflicts.</p>
<h2 data-number="7.8" id="design-choice-templated-type-aware-operator-delete-is-a-usual-deallocation-function"><span class="header-section-number">7.8</span> Design choice: Templated
type-aware <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
is a <em>usual deallocation function</em><a href="#design-choice-templated-type-aware-operator-delete-is-a-usual-deallocation-function" class="self-link"></a></h2>
<p>Allowing type-aware <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
does require changes to the definition of usual deallocation functions,
but the changes are conceptually simple and the cost of not supporting
this case is extremely high.</p>
<p>In the current specification, we place very tight requirements on
what an <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
declaration can look like in order to be considered a <em>usual
deallocation function</em>. The reason this definition previously
disallowed function templates is that all of the implicit parameters are
monomorphic types. That restriction made sense previously.</p>
<p>However, this proposal introduces a new form of the operators for
which it is correct (even expected) to be a function template. To that
end, we allow a templated <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
to be considered a usual deallocation function, as long as the only
dependently-typed parameter is the first <code class="sourceCode cpp">std<span class="op">::</span>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
parameter. To our minds, these semantics match the “intent” of the
restrictions already in place for the other implicit parameters like
<code class="sourceCode cpp">std<span class="op">::</span>align_val_t</code>.</p>
<p>The cost of not allowing a templated type-aware <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
as a usual deallocation function is very high, as it functionally
prohibits the use of type-aware allocation operators in any environment
that requires the ability to clean up after a constructor has thrown an
exception.</p>
<h2 data-number="7.9" id="design-choice-no-support-for-type-aware-destroying-delete"><span class="header-section-number">7.9</span> Design choice: No support for
type-aware destroying delete<a href="#design-choice-no-support-for-type-aware-destroying-delete" class="self-link"></a></h2>
<p>We have decided not to support type-aware destroying delete as we
believe it creates a user hazard. At a technical level there is no
additional complexity in supporting type-aware destroying delete, but
the resulting semantics seem likely to cause a lot of confusion. For
example, given this hypothetical declaration:</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Foo <span class="op">{</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb28-3"><a href="#cb28-3" 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="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> <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>, Foo<span class="op">*</span>, std<span class="op">::</span>destroying_delete_t<span class="op">)</span>;</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Bar <span class="op">:</span> Foo <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-9"><a href="#cb28-9" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> f<span class="op">(</span>Foo<span class="op">*</span> foo<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-10"><a href="#cb28-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">delete</span> foo; <span class="co">// calls Foo::operator delete&lt;Foo&gt;</span></span>
<span id="cb28-11"><a href="#cb28-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb28-12"><a href="#cb28-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-13"><a href="#cb28-13" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> g<span class="op">(</span>Bar <span class="op">*</span>bar<span class="op">)</span> <span class="op">{</span></span>
<span id="cb28-14"><a href="#cb28-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">delete</span> bar; <span class="co">// calls Foo::operator delete&lt;Bar&gt;</span></span>
<span id="cb28-15"><a href="#cb28-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>To a user this appears to be doing what they expect. However,
consider the following:</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Oops <span class="op">:</span> Bar <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> h<span class="op">(</span>Oops <span class="op">*</span>oops<span class="op">)</span> <span class="op">{</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>  g<span class="op">(</span>oops<span class="op">)</span>; <span class="co">// calls Foo::operator delete&lt;Bar&gt; from within g()</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>By design, destroying delete does not perform any polymorphic
dispatch, and as a result the type being passed to the operator is not
be the dynamic type of the object being destroyed, but rather its static
type. As a result, basic functionality will appear to work correctly
from the user’s point of view when in reality the rules are much subtler
than they seem.</p>
<p>Given that the design intent of destroying delete is for users to
manage destruction and dispatching manually, we believe that adding
type-awareness to destroying delete will add little value while creating
the potential for confusion, so we decided not to do it.</p>
<h2 data-number="7.10" id="design-choice-dropped-support-for-adl"><span class="header-section-number">7.10</span> Design choice: Dropped support
for ADL<a href="#design-choice-dropped-support-for-adl" class="self-link"></a></h2>
<p>The initial proposal allowed the specification of type-aware
operators in namespaces that would then be resolved via ADL. Upon
further consideration, this introduces a number of challenges that are
difficult to resolve robustly. As a result, we have dropped support for
namespace-scope operator declarations and removed the use of ADL from
the proposal.</p>
<p>The first problem is that ADL would be based on the type of all
arguments passed to <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>,
including placement arguments. While this is not a problem for <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
itself, <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
does not get the same placement arguments, which would potentially
change the set of associated namespaces used to resolve
<code class="sourceCode cpp"><span class="kw">new</span></code> and
<code class="sourceCode cpp"><span class="kw">delete</span></code>.</p>
<p>One of our original motivations for allowing namespace-scoped
operators was to simplify the task of providing operators for a whole
library. However, since ADL is so viral, the set of associated
namespaces can easily grow unintentionally (e.g. <code class="sourceCode cpp"><span class="kw">new</span> lib1<span class="op">::</span>Foo<span class="op">&lt;</span>lib2<span class="op">::</span>Bar<span class="op">&gt;(...)</span></code>),
which means that developers would have to appropriately constrain their
type-aware operators anyway. In other words, we believe that a
declaration like this would never have been a good idea in the first
place:</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> lib <span class="op">{</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// intent: override for all types in this namespace</span></span>
<span id="cb30-3"><a href="#cb30-3" 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="cb30-4"><a href="#cb30-4" 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>type_identity<span class="op">&lt;</span>T<span class="op">&gt;</span>, std<span class="op">::</span><span class="dt">size_t</span><span class="op">)</span>;</span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>There are too many ways in which an unconstrained declaration like
this can break, including an unexpected set of associated namespaces or
even a mere <code class="sourceCode cpp"><span class="kw">using</span> <span class="kw">namespace</span> lib;</code>.</p>
<p>Given the need to constrain a type-aware operator anyway, we believe
that allowing namespace-scoped operators is merely a nice-to-have but
not something that we need fundamentally. Furthermore, adding this
capability to the language could always be pursued as a separate
proposal since that concern can be tackled orthogonally. For example, a
special ADL lookup could be done based solely on the dynamic type being
[de]allocated.</p>
<p>Since this adds complexity to the proposal and implementation and
doesn’t provide great value, we are not pursuing it as part of this
proposal.</p>
<h2 data-number="7.11" id="interactions-with-stdallocatort"><span class="header-section-number">7.11</span> Interactions with <code class="sourceCode cpp">std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code><a href="#interactions-with-stdallocatort" class="self-link"></a></h2>
<p>Today, <code class="sourceCode cpp">std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;::</span>allocate</code>
is specified to call <code class="sourceCode cpp"><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></code>
explicitly. Even if <code class="sourceCode cpp">T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>
exists, <code class="sourceCode cpp">std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
will not attempt to call it. We view this as a defect in the current
standard since <code class="sourceCode cpp">std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
could instead select the same operator that would be called in an
expression like <code class="sourceCode cpp"><span class="kw">new</span> T<span class="op">(...)</span></code>
(without the constructor call, obviously).</p>
<p>This doesn’t have an interaction with our proposal, except for making
<code class="sourceCode cpp">std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>’s
behavior a bit more unfortunate than it already is today. Indeed, users
may rightly expect that <code class="sourceCode cpp">std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
will call their type-aware <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
when in reality that won’t be the case.</p>
<p>Since this deception already exists for <code class="sourceCode cpp">T<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>,
we do not attempt to change <code class="sourceCode cpp">std<span class="op">::</span>allocator<span class="op">&lt;</span>T<span class="op">&gt;</span></code>’s
behavior in this proposal. However, the authors are willing to
investigate fixing this issue as a separate proposal, which will
certainly present its own set of challenges (e.g. constant
evaluation).</p>
<h2 data-number="7.12" id="odr-implications-and-mismatched-operator-new-operator-delete"><span class="header-section-number">7.12</span> ODR implications and
mismatched <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
/ <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code><a href="#odr-implications-and-mismatched-operator-new-operator-delete" class="self-link"></a></h2>
<p>A concern that was raised in St-Louis was that this proposal would
increase the likelihood of ODR violation caused by different
declarations of <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>/<code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
being used in different TUs. For example, one TU would get <code class="sourceCode cpp">lib1<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>
and another TU would use <code class="sourceCode cpp">lib2<span class="op">::</span><span class="kw">operator</span> <span class="kw">delete</span></code>
due to e.g. a different set of headers being included. Note that the
exact same issue also applies to every other operator that is commonly
used via ADL (like <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">+</span></code>),
except that many such ODR violations may end up being more benign than a
mismatched
<code class="sourceCode cpp"><span class="kw">new</span></code>/<code class="sourceCode cpp"><span class="kw">delete</span></code>.</p>
<p>First, we believe that the only way to avoid this issue (in general)
is to properly constrain templated declarations, and nothing can prevent
users from doing that incorrectly. However, since this proposal has
dropped the ADL lookup, declarations of type-aware operators must now be
in-class or global. This greatly simplifies the selection of an
operator, which should make it harder for users to unexpectedly define
an insufficiently constrained operator without immediately getting a
compilation error.</p>
<p>Furthermore, without ADL lookup, the ODR implications of this
proposal are exactly the same as the existing ODR implications of
user-defined placement new operators, which can be templates.</p>
<h2 data-number="7.13" id="impact-on-the-library"><span class="header-section-number">7.13</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 cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
variants in the standard library at this time, althought this could be
investigated in the future.</p>
<h2 data-number="7.14" id="interactions-with-coroutines"><span class="header-section-number">7.14</span> Interactions with coroutines<a href="#interactions-with-coroutines" class="self-link"></a></h2>
<p>Coroutines currently allow using a custom <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">new</span></code>
and <code class="sourceCode cpp"><span class="kw">operator</span> <span class="kw">delete</span></code>
for allocating the coroutine frame. That is done by looking up in the
coroutine’s promise type for <code class="sourceCode cpp">Promise<span class="op">::</span><span class="kw">operator</span> <span class="kw">new</span></code>.
However, there is no mechanism to communicate the type being allocated,
since that type is only something known by the compiler (and fairly late
during translation). This paper does not propose changing how allocation
for coroutine frames is customized. In the future, the coroutine
specification could be updated to make the type being allocated more
visible and to use a typed allocation function, but there is significant
enough design space to avoid doing that here.</p>
<h1 data-number="8" id="acknowledgments"><span class="header-section-number">8</span> Acknowledgments<a href="#acknowledgments" class="self-link"></a></h1>
<p>We’d like to acknowledge the time spent by Jens Maurer, Brian Bi,
Corentin Jabot, Richard Smith, Hana Dusikova, and others to help us
develop the wording in this proposal.</p>
</div>
</div>
</body>
</html>
