<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <meta name="dcterms.date" content="2024-10-16" />
  <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>P2719R1</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>2024-10-16</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      Evolution<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Louis Dionne<br>&lt;<a href="mailto:ldionne@apple.com" class="email">ldionne@apple.com</a>&gt;<br>
      Oliver Hunt<br>&lt;<a href="mailto:oliver@apple.com" class="email">oliver@apple.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<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>
<ul>
<li><a href="#a-concrete-use-case" id="toc-a-concrete-use-case"><span class="toc-section-number">3.1</span> A concrete use
case<span></span></a></li>
</ul></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>
<ul>
<li><a href="#free-function-example" id="toc-free-function-example"><span class="toc-section-number">5.1</span> Free function
example<span></span></a></li>
<li><a href="#in-class-example" id="toc-in-class-example"><span class="toc-section-number">5.2</span> In-class
example<span></span></a></li>
</ul></li>
<li><a href="#design-choices-and-notes" id="toc-design-choices-and-notes"><span class="toc-section-number">6</span> Design choices and
notes<span></span></a>
<ul>
<li><a href="#design-choice-stdtype_identityt-vs-raw-template-argument" id="toc-design-choice-stdtype_identityt-vs-raw-template-argument"><span class="toc-section-number">6.1</span> Design choice:
<code class="sourceCode default">std::type_identity&lt;T&gt;</code> vs
“raw” template argument<span></span></a></li>
<li><a href="#design-choice-stdtype_identityt-vs-t" id="toc-design-choice-stdtype_identityt-vs-t"><span class="toc-section-number">6.2</span> Design choice:
<code class="sourceCode default">std::type_identity&lt;T&gt;</code> vs
<code class="sourceCode default">T*</code><span></span></a></li>
<li><a href="#design-choice-location-of-stdtype_identityt" id="toc-design-choice-location-of-stdtype_identityt"><span class="toc-section-number">6.3</span> Design choice: Location of
<code class="sourceCode default">std::type_identity&lt;T&gt;</code><span></span></a></li>
<li><a href="#design-choice-templated-type-aware-operator-delete-is-a-usual-deallocation-function" id="toc-design-choice-templated-type-aware-operator-delete-is-a-usual-deallocation-function"><span class="toc-section-number">6.4</span> Design choice: Templated
type-aware <code class="sourceCode default">operator delete</code> is a
<em>usual deallocation function</em><span></span></a></li>
<li><a href="#design-choice-no-support-for-type-aware-destroying-delete" id="toc-design-choice-no-support-for-type-aware-destroying-delete"><span class="toc-section-number">6.5</span> Design choice: No support for
type-aware destroying delete<span></span></a></li>
<li><a href="#design-choice-dropped-support-for-adl" id="toc-design-choice-dropped-support-for-adl"><span class="toc-section-number">6.6</span> Design choice: Dropped support for
ADL<span></span></a></li>
<li><a href="#interactions-with-stdallocatort" id="toc-interactions-with-stdallocatort"><span class="toc-section-number">6.7</span> Interactions with
<code class="sourceCode default">std::allocator&lt;T&gt;</code><span></span></a></li>
<li><a href="#odr-implications-and-mismatched-operator-new-operator-delete" id="toc-odr-implications-and-mismatched-operator-new-operator-delete"><span class="toc-section-number">6.8</span> ODR implications and mismatched
<code class="sourceCode default">operator new</code> /
<code class="sourceCode default">operator delete</code><span></span></a></li>
<li><a href="#impact-on-the-library" id="toc-impact-on-the-library"><span class="toc-section-number">6.9</span> Impact on the
library<span></span></a></li>
</ul></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 default">operator new</code> can be provided as
a static member function of a class, like
<code class="sourceCode default">void* T::operator new</code>. If such a
declaration is provided, an expression like
<code class="sourceCode default">new T(...)</code> will use that
allocation function. Otherwise, the global version of
<code class="sourceCode default">operator new</code> can be replaced by
users in a type-agnostic way, by implementing
<code class="sourceCode default">void* operator new(size_t)</code> and
its variants. A similar mechanism exists for
<em>delete-expressions</em>.</p>
<p>This paper proposes an extension to <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 default">std::type_identity&lt;T&gt;</code> tag
argument that allows the provision of the concrete type to
<code class="sourceCode default">operator new</code> and
<code class="sourceCode default">operator delete</code>. In addition to
providing valuable information to the allocator, this allows the
creation of type-specific
<code class="sourceCode default">operator new</code> and
<code class="sourceCode default">operator delete</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: Initial version</li>
<li>R1:
<ul>
<li>Simplified the lookup mechanism by removing the need to perform ADL
(based on implementation experience)</li>
<li>Allowed <code class="sourceCode default">std::type_identity</code>
parameter for in-class
<code class="sourceCode default">T::operator new</code> for
consistency</li>
<li>Made <code class="sourceCode default">std::type_identity</code> as
the first parameter</li>
<li>Documented design choices and changes based on feedback and
implementation experience</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 default">T::operator new</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 default">operator new</code> via the usual
link-time mechanism and running into problems because they really only
intended for their custom
<code class="sourceCode default">operator new</code> to be used within
their own code, not by all the code in their process. For example, we’ve
seen scenarios where multiple libraries attempt to replace the global
<code class="sourceCode default">operator new</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 default">operator new</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 default">T::operator new</code>), and then a
lookup in the global scope (for
<code class="sourceCode default">::operator new</code>) if the previous
one failed. Once the name lookup has been done and the compiler has
decided whether it was looking for
<code class="sourceCode default">T::operator new</code> or
<code class="sourceCode default">::operator new</code>, name lookup will
not be done again even if the steps that follow were to fail. From here
on, let’s denote by <code class="sourceCode default">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 default">T</code> has a
new-extended alignment or not. For the sake of simplicity, assume that
<code class="sourceCode default">T</code> does not have a new-extended
alignment. The compiler starts by performing overload resolution as-if
the following expression were used:</p>
<div class="sourceCode" id="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 default">T</code> that has new-extended
alignment, the order of the two overload resolutions performed above is
simply reversed.</p>
<p>Delete-expressions behave similarly, with lookup being performed in
the context of the 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 default">operator delete</code> (with or without
a <code class="sourceCode default">size_t</code> parameter depending on
whether the considered
<code class="sourceCode default">operator delete</code> is a member
function or not).</p>
<h1 data-number="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 default">std::type_identity&lt;T&gt;</code> to
<code class="sourceCode default">operator new</code> and
<code class="sourceCode default">operator delete</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 default">std::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 default">std::type_identity&lt;T&gt;</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 default">std::type_identity&lt;T&gt;</code>,
with a higher priority than the existing size and alignment parameters.
For illustration, here is how overload resolution changes
(<code class="sourceCode default">NEW</code> is the set of candidates
found by name lookup for
<code class="sourceCode default">operator new</code>, and
<code class="sourceCode default">DELETE</code> is the equivalent for
<code class="sourceCode default">operator delete</code>).</p>
<p>If the user writes
<code class="sourceCode default">new T(...)</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="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="dt">size_t</span><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="dt">size_t</span><span class="op">)</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>NEW<span class="op">(</span><span class="dt">size_t</span><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="dt">size_t</span>, align_val_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="dt">size_t</span><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="dt">size_t</span>, align_val_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="dt">size_t</span><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="dt">size_t</span>, align_val_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="dt">size_t</span><span class="op">)</span></span></code></pre></div>

</div></td>
</tr>
</tbody>
</table>
<p>If the user writes
<code class="sourceCode default">delete 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>
<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>, <span class="dt">size_t</span><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></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>
<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="dt">void</span><span class="op">*</span>, <span class="dt">size_t</span><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="dt">void</span><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>, <span class="dt">size_t</span><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></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>
<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>, <span class="dt">size_t</span>, align_val_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>, align_val_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></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>
<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="dt">void</span><span class="op">*</span>, <span class="dt">size_t</span>, align_val_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="dt">void</span><span class="op">*</span>, align_val_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="dt">void</span><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>, <span class="dt">size_t</span>, align_val_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>, align_val_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></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 default">operator delete</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 default">operator delete</code> must have the
same type-awareness as the preceding
<code class="sourceCode default">operator new</code> or the program is
considered ill-formed.</p>
<p>For clarity, in types with virtual destructors,
<code class="sourceCode default">operator delete</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 default">delete this</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>
<blockquote>
<p>Note: The above is for illustrative purposes only: it is a bad idea
to provide a fully unconstrained type-aware
<code class="sourceCode default">operator new</code>.</p>
</blockquote>
<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>
<!--
# Wording

To effectively support this proposal, it is necessary to update the definition of a usual deallocation function
([basic.stc.dynamic.deallocation](https://timsong-cpp.github.io/cppwp/n4950/basic.stc.dynamic.deallocation)) to
include this new parameter, which requires the following:

* Allow the first parameter to be a specialization of `std::type_identity`, and update to position requirements of later
  parameters to include that.
* Allow the function to have template parameters as long as the function is `operator delete` and the
  only dependent parameter is a `std::type_identity` specialization in the first parameter position.
-->
<h1 data-number="6" id="design-choices-and-notes"><span class="header-section-number">6</span> Design choices and notes<a href="#design-choices-and-notes" class="self-link"></a></h1>
<h2 data-number="6.1" id="design-choice-stdtype_identityt-vs-raw-template-argument"><span class="header-section-number">6.1</span> Design choice:
<code class="sourceCode default">std::type_identity&lt;T&gt;</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 default">std::type_identity&lt;T&gt;</code> as a
tag, the compiler would search as per the following expression:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">operator</span> <span class="kw">new</span><span class="op">&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 default">std::type_identity&lt;T&gt;</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 default">operator new</code> and
<code class="sourceCode default">operator delete</code>
declarations.</p>
<p>For example, a valid
<code class="sourceCode default">operator new</code> declaration today
would be:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">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="cb16-2"><a href="#cb16-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 default">new (42) int(3)</code> which would
result in a call like <code class="sourceCode default">operator new&lt;int&gt;(sizeof(int), 42)</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 default">operator delete</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="6.2" id="design-choice-stdtype_identityt-vs-t"><span class="header-section-number">6.2</span> Design choice:
<code class="sourceCode default">std::type_identity&lt;T&gt;</code> vs
<code class="sourceCode default">T*</code><a href="#design-choice-stdtype_identityt-vs-t" class="self-link"></a></h2>
<p>This proposal uses
<code class="sourceCode default">std::type_identity&lt;T&gt;</code> as a
tag argument rather than passing a first argument of type
<code class="sourceCode default">T*</code>. At first sight, passing
<code class="sourceCode default">T*</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 default">std::type_identity</code>.</p>
<h3 data-number="6.2.1" id="problems-with-the-value-being-passed"><span class="header-section-number">6.2.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="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">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="cb17-2"><a href="#cb17-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="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="co">// T* ptr = new T(...)</span></span>
<span id="cb18-2"><a href="#cb18-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="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="co">// delete ptr</span></span>
<span id="cb18-5"><a href="#cb18-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 default">operator new</code> can’t
be anything but a null pointer. However, for
<code class="sourceCode default">operator delete</code> we can be
assured that people will be confused about receiving two pointer
parameters, where the explicitly typed parameter is
<code class="sourceCode default">nullptr</code>. Also note that we
cannot pass the object pointer through that parameter as
<code class="sourceCode default">operator delete</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 default">T</code> object, which would be
undefined behavior.</p>
<h3 data-number="6.2.2" id="silent-conversions-to-base-types"><span class="header-section-number">6.2.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="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">struct</span> Base <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb19-2"><a href="#cb19-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="cb19-3"><a href="#cb19-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 default">Base</code>, which may or may not be
intended. If not intended, the conversion from
<code class="sourceCode default">Derived*</code> to
<code class="sourceCode default">Base*</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="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> Base <span class="op">{</span></span>
<span id="cb20-2"><a href="#cb20-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="cb20-3"><a href="#cb20-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="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-5"><a href="#cb20-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="cb20-6"><a href="#cb20-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="cb20-7"><a href="#cb20-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="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>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="cb21-2"><a href="#cb21-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="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-4"><a href="#cb21-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="cb21-5"><a href="#cb21-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>
<h3 data-number="6.2.3" id="performance-considerations"><span class="header-section-number">6.2.3</span> Performance considerations<a href="#performance-considerations" class="self-link"></a></h3>
<p>There is a fundamental difference between
<code class="sourceCode default">T*</code> and
<code class="sourceCode default">std::type_identity&lt;T&gt;</code> in
that <code class="sourceCode default">T*</code> is a type that has an
actual value and size, whereas
<code class="sourceCode default">std::type_identity</code> is a zero
sized record. This difference means that the
<code class="sourceCode default">T*</code> model results in an
additional parameter being required in the generated code, whereas the
zero sized <code class="sourceCode default">type_identity</code>
parameter does not exist in the majority of calling conventions. In
principle this difference should be minor for templated operators as
they are typically inlined and so the calling convention is not
relevant, but for non-template definitions the implementation can be out
of line, and so the difference may matter.</p>
<p>For all of these reasons, we believe that a tag type like
<code class="sourceCode default">std::type_identity</code> is the right
design choice.</p>
<h2 data-number="6.3" id="design-choice-location-of-stdtype_identityt"><span class="header-section-number">6.3</span> Design choice: Location of
<code class="sourceCode default">std::type_identity&lt;T&gt;</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="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="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="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">(</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="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="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="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">(</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="cb22-6"><a href="#cb22-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="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">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="cb23-2"><a href="#cb23-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="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-4"><a href="#cb23-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="cb23-5"><a href="#cb23-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="cb23-6"><a href="#cb23-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>
<!--
TODO(Louis): I don't understand this paragraph

An alternative to this would be to require passing an implicit `type_identity` parameter to require the relevant
parameter in the original function declaration always be a `type_identity<T>` specialization, similar to our
definition of type-aware allocators in general. This would differ from the behavior with respect to other implicit
parameters that are permitted to bind to arbitrary template parameters.
-->
<h2 data-number="6.4" id="design-choice-templated-type-aware-operator-delete-is-a-usual-deallocation-function"><span class="header-section-number">6.4</span> Design choice: Templated
type-aware <code class="sourceCode default">operator delete</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 default">operator delete</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 default">operator delete</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 default">operator delete</code> to be considered
a usual deallocation function, as long as the only dependently-typed
parameter is the first
<code class="sourceCode default">std::type_identity&lt;T&gt;</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 default">std::align_val_t</code>.</p>
<p>The cost of not allowing a templated type-aware
<code class="sourceCode default">operator delete</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="6.5" id="design-choice-no-support-for-type-aware-destroying-delete"><span class="header-section-number">6.5</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="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> Foo <span class="op">{</span></span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">...</span></span>
<span id="cb24-3"><a href="#cb24-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="cb24-4"><a href="#cb24-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="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-7"><a href="#cb24-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="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-9"><a href="#cb24-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="cb24-10"><a href="#cb24-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="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-13"><a href="#cb24-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="cb24-14"><a href="#cb24-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="cb24-15"><a href="#cb24-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="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">struct</span> Oops <span class="op">:</span> Bar <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb25-3"><a href="#cb25-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="cb25-4"><a href="#cb25-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="cb25-5"><a href="#cb25-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="6.6" id="design-choice-dropped-support-for-adl"><span class="header-section-number">6.6</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 default">operator new</code>, including
placement arguments. While this is not a problem for
<code class="sourceCode default">operator new</code> itself,
<code class="sourceCode default">operator delete</code> does not get the
same placement arguments, which would potentially change the set of
associated namespaces used to resolve
<code class="sourceCode default">new</code> and
<code class="sourceCode default">delete</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 default">new lib1::Foo&lt;lib2::Bar&gt;(...)</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="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">namespace</span> lib <span class="op">{</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// intent: override for all types in this namespace</span></span>
<span id="cb26-3"><a href="#cb26-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="cb26-4"><a href="#cb26-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="cb26-5"><a href="#cb26-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 default">using namespace 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="6.7" id="interactions-with-stdallocatort"><span class="header-section-number">6.7</span> Interactions with
<code class="sourceCode default">std::allocator&lt;T&gt;</code><a href="#interactions-with-stdallocatort" class="self-link"></a></h2>
<p>Today, <code class="sourceCode default">std::allocator&lt;T&gt;::allocate</code> is
specified to call
<code class="sourceCode default">::operator new(std::size_t)</code>
explicitly. Even if
<code class="sourceCode default">T::operator new</code> exists,
<code class="sourceCode default">std::allocator&lt;T&gt;</code> will not
attempt to call it. We view this as a defect in the current Standard
since <code class="sourceCode default">std::allocator&lt;T&gt;</code>
could instead select the same operator that would be called in an
expression like <code class="sourceCode default">new T(...)</code>
(without the constructor call, obviously).</p>
<p>This doesn’t have an interaction with our proposal, except for making
<code class="sourceCode default">std::allocator&lt;T&gt;</code>’s
behavior a bit more unfortunate than it already is today. Indeed, users
may rightly expect that
<code class="sourceCode default">std::allocator&lt;T&gt;</code> will
call their type-aware
<code class="sourceCode default">operator new</code> when in reality
that won’t be the case.</p>
<p>Since this deception already exists for
<code class="sourceCode default">T::operator new</code>, we do not
attempt to change
<code class="sourceCode default">std::allocator&lt;T&gt;</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="6.8" id="odr-implications-and-mismatched-operator-new-operator-delete"><span class="header-section-number">6.8</span> ODR implications and mismatched
<code class="sourceCode default">operator new</code> /
<code class="sourceCode default">operator delete</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 default">operator new</code>/<code class="sourceCode default">operator delete</code>
being used in different TUs. For example, one TU would get
<code class="sourceCode default">lib1::operator new</code> and another
TU would use
<code class="sourceCode default">lib2::operator delete</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 default">operator+</code>), except that
many such ODR violations may end up being more benign than a mismatched
<code class="sourceCode default">new</code>/<code class="sourceCode default">delete</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="6.9" id="impact-on-the-library"><span class="header-section-number">6.9</span> Impact on the library<a href="#impact-on-the-library" class="self-link"></a></h2>
<p>This proposal does not have any impact on the library, since this
only tweaks the search process performed by the compiler when it
evaluates a new-expression and a delete-expression. In particular, we do
not propose adding new type-aware free function
<code class="sourceCode default">operator new</code> variants in the
standard library at this time, althought this could be investigated in
the future.</p>
</div>
</div>
</body>
</html>
