<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
  <meta charset="utf-8" />
  <meta name="generator" content="mpark/wg21" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
  <title>Move `resource_adaptor` from Library TS to the C++ WP</title>
  <style>
      code{white-space: pre-wrap;}
      span.smallcaps{font-variant: small-caps;}
      span.underline{text-decoration: underline;}
      div.column{display: inline-block; vertical-align: top; width: 50%;}
      div.csl-block{margin-left: 1.5em;}
      ul.task-list{list-style: none;}
      pre > code.sourceCode { white-space: pre; position: relative; }
      pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
      pre > code.sourceCode > span:empty { height: 1.2em; }
      .sourceCode { overflow: visible; }
      code.sourceCode > span { color: inherit; text-decoration: inherit; }
      div.sourceCode { margin: 1em 0; }
      pre.sourceCode { margin: 0; }
      @media screen {
      div.sourceCode { overflow: auto; }
      }
      @media print {
      pre > code.sourceCode { white-space: pre-wrap; }
      pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
      }
      pre.numberSource code
        { counter-reset: source-line 0; }
      pre.numberSource code > span
        { position: relative; left: -4em; counter-increment: source-line; }
      pre.numberSource code > span > a:first-child::before
        { content: counter(source-line);
          position: relative; left: -1em; text-align: right; vertical-align: baseline;
          border: none; display: inline-block;
          -webkit-touch-callout: none; -webkit-user-select: none;
          -khtml-user-select: none; -moz-user-select: none;
          -ms-user-select: none; user-select: none;
          padding: 0 4px; width: 4em;
          color: #aaaaaa;
        }
      pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
      div.sourceCode
        {  background-color: #f6f8fa; }
      @media screen {
      pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
      }
      code span { } /* Normal */
      code span.al { color: #ff0000; } /* Alert */
      code span.an { } /* Annotation */
      code span.at { } /* Attribute */
      code span.bn { color: #9f6807; } /* BaseN */
      code span.bu { color: #9f6807; } /* BuiltIn */
      code span.cf { color: #00607c; } /* ControlFlow */
      code span.ch { color: #9f6807; } /* Char */
      code span.cn { } /* Constant */
      code span.co { color: #008000; font-style: italic; } /* Comment */
      code span.cv { color: #008000; font-style: italic; } /* CommentVar */
      code span.do { color: #008000; } /* Documentation */
      code span.dt { color: #00607c; } /* DataType */
      code span.dv { color: #9f6807; } /* DecVal */
      code span.er { color: #ff0000; font-weight: bold; } /* Error */
      code span.ex { } /* Extension */
      code span.fl { color: #9f6807; } /* Float */
      code span.fu { } /* Function */
      code span.im { } /* Import */
      code span.in { color: #008000; } /* Information */
      code span.kw { color: #00607c; } /* Keyword */
      code span.op { color: #af1915; } /* Operator */
      code span.ot { } /* Other */
      code span.pp { color: #6f4e37; } /* Preprocessor */
      code span.re { } /* RegionMarker */
      code span.sc { color: #9f6807; } /* SpecialChar */
      code span.ss { color: #9f6807; } /* SpecialString */
      code span.st { color: #9f6807; } /* String */
      code span.va { } /* Variable */
      code span.vs { color: #9f6807; } /* VerbatimString */
      code span.wa { color: #008000; font-weight: bold; } /* Warning */
      code.diff {color: #898887}
      code.diff span.va {color: #006e28}
      code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
text-align: left;
}
@media screen and (max-width: 30em) {
body {
margin: 1.5em;
}
}
div.wrapper {
max-width: 60em;
margin: auto;
}

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

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

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

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

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

code.sourceCode > span { display: inline; }
</style>
  <link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
  
  <!--[if lt IE 9]>
    <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
  <![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">Move
<code class="sourceCode cpp">resource_adaptor</code> from Library TS to
the C++ WP</h1>
<table style="border:none;float:right">
  <tr>
    <td>Document #:</td>
    <td>P1083R8</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td><!-- $TimeStamp$ -->
2024-05-22 10:56 EDT<!-- $ --></td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project:</td>
    <td>Programming Language C++</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Audience:</td>
    <td>
      LEWG/LWG<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to:</td>
    <td>
      Pablo Halpern<br>&lt;<a href="mailto:phalpern@halpernwightsoftware.com" class="email">phalpern@halpernwightsoftware.com</a>&gt;<br>
    </td>
  </tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#abstract" id="toc-abstract"><span class="toc-section-number">1</span> Abstract<span></span></a></li>
<li><a href="#status" id="toc-status"><span class="toc-section-number">2</span> Status<span></span></a></li>
<li><a href="#change-history" id="toc-change-history"><span class="toc-section-number">3</span> Change History<span></span></a>
<ul>
<li><a href="#changes-from-r7-to-r8-pre-st.-louis-2024" id="toc-changes-from-r7-to-r8-pre-st.-louis-2024"><span class="toc-section-number">3.1</span> Changes from R7 to R8 (pre
St. Louis 2024)<span></span></a></li>
<li><a href="#changes-from-r6-to-r7-pre-kona-2022" id="toc-changes-from-r6-to-r7-pre-kona-2022"><span class="toc-section-number">3.2</span> Changes from R6 to R7 (pre Kona
2022)<span></span></a></li>
<li><a href="#changes-from-r5-to-r6-from-lewg-telcon" id="toc-changes-from-r5-to-r6-from-lewg-telcon"><span class="toc-section-number">3.3</span> Changes from R5 to R6 (from LEWG
telcon)<span></span></a></li>
<li><a href="#changes-from-r4-to-r5-from-lwg-reflector-discussion" id="toc-changes-from-r4-to-r5-from-lwg-reflector-discussion"><span class="toc-section-number">3.4</span> Changes from R4 to R5 (from LWG
reflector discussion)<span></span></a></li>
<li><a href="#changes-from-r3-to-r4-from-lwg-telcon" id="toc-changes-from-r3-to-r4-from-lwg-telcon"><span class="toc-section-number">3.5</span> Changes from R3 to R4 (from LWG
telcon)<span></span></a></li>
<li><a href="#changes-from-r2-to-r3-in-kona-and-pre-cologne" id="toc-changes-from-r2-to-r3-in-kona-and-pre-cologne"><span class="toc-section-number">3.6</span> Changes from R2 to R3 (in Kona and
pre-Cologne)<span></span></a></li>
<li><a href="#changes-from-r1-to-r2-in-san-diego" id="toc-changes-from-r1-to-r2-in-san-diego"><span class="toc-section-number">3.7</span> Changes from R1 to R2 (in San
Diego)<span></span></a></li>
<li><a href="#changes-from-r0-to-r1-pre-san-diego" id="toc-changes-from-r0-to-r1-pre-san-diego"><span class="toc-section-number">3.8</span> Changes from R0 to R1 (pre-San
Diego)<span></span></a></li>
</ul></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">4</span> Motivation<span></span></a></li>
<li><a href="#summary-of-proposal" id="toc-summary-of-proposal"><span class="toc-section-number">5</span> Summary of
Proposal<span></span></a></li>
<li><a href="#design-changes-r6-to-current-for-lewg-review" id="toc-design-changes-r6-to-current-for-lewg-review"><span class="toc-section-number">6</span> Design changes R6 to current (for
LEWG review)<span></span></a></li>
<li><a href="#impact-on-the-standard" id="toc-impact-on-the-standard"><span class="toc-section-number">7</span> Impact on the
standard<span></span></a></li>
<li><a href="#implementation-experience" id="toc-implementation-experience"><span class="toc-section-number">8</span> Implementation
Experience<span></span></a></li>
<li><a href="#formal-wording" id="toc-formal-wording"><span class="toc-section-number">9</span> Formal Wording<span></span></a></li>
<li><a href="#bibliography" id="toc-bibliography"><span class="toc-section-number">10</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="abstract"><span class="header-section-number">1</span> Abstract<a href="#abstract" class="self-link"></a></h1>
<p>The <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>
class template in the Library Fundamentals TS wraps an object whose type
that meets the allocator requirements and gives it a <code class="sourceCode cpp">pmr<span class="op">::</span>memory_resource</code>
interface. When the polymorphic allocator infrastructure was moved from
the Library Fundamentals TS to the C++17 working draft, <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>
was left behind. The decision not to move <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>
was deliberately conservative, but the absence of
<code class="sourceCode cpp">resource_adaptor</code> in the standard is
a hole that must be plugged for a smooth use of
<code class="sourceCode cpp">pmr</code> allocators as a simplified,
non-template, allocator model that is fully compatible with the general
C++ template-argument allocator model. This paper proposes that <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>
be moved from the LFTS, slightly modified, and added to the C++26
working draft.</p>
<h1 data-number="2" id="status"><span class="header-section-number">2</span> Status<a href="#status" class="self-link"></a></h1>
<p>On Oct 5, 2021, a subgroup of LWG reviewed P1083R3 and found an issue
in the way the max alignment supported by <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>
was specified in the paper. There was general consensus that a
<code class="sourceCode cpp">MaxAlign</code> template parameter would be
preferable, but the change was considered to be of a design nature and
therefore requires LEWG review. The R4 revision of this paper contains
the changes from LEWG review and the R5 revision contains fixes
identified in the LWG reflector discussion that followed.</p>
<p>On March 15, 2022 LEWG reviewed <span class="citation" data-cites="P1083R5">[<a href="https://wg21.link/p1083r5" role="doc-biblioref">P1083R5</a>]</span> in a telcon. Because of
scheduling and technical concerns, it was decided that the paper was not
ready for C++23 but that the paper should be revised and brought back to
LEWG with the intent of forwarding for C++26. The R6 revision contains
the fixes required by LEWG and the R7 revision added a missing
<code class="sourceCode cpp"><span class="kw">noexcept</span></code> and
improved the LWG wording in one small section.</p>
<p>This version brings the paper up to date with the latest WP and
should be ready for final LEWG review and (re)forwarding to LWG.</p>
<h1 data-number="3" id="change-history"><span class="header-section-number">3</span> Change History<a href="#change-history" class="self-link"></a></h1>
<h2 data-number="3.1" id="changes-from-r7-to-r8-pre-st.-louis-2024"><span class="header-section-number">3.1</span> Changes from R7 to R8 (pre
St. Louis 2024)<a href="#changes-from-r7-to-r8-pre-st.-louis-2024" class="self-link"></a></h2>
<ul>
<li>Re-based to April 2024 WP <span class="citation" data-cites="N4981">[<a href="https://wg21.link/n4981" role="doc-biblioref">N4981</a>]</span> and updated status.</li>
<li>Added variadic constructor to <em>resource-adaptor-imp</em>.</li>
</ul>
<h2 data-number="3.2" id="changes-from-r6-to-r7-pre-kona-2022"><span class="header-section-number">3.2</span> Changes from R6 to R7 (pre Kona
2022)<a href="#changes-from-r6-to-r7-pre-kona-2022" class="self-link"></a></h2>
<ul>
<li>Reworded additional requirements on the
<code class="sourceCode cpp">Allocator</code> parameter to follow the
proper voice of the standard (thanks to Daniel Kruegler).</li>
<li>Added
<code class="sourceCode cpp"><span class="kw">noexcept</span></code> to
<code class="sourceCode cpp">get_adapted_allocator</code>.</li>
</ul>
<h2 data-number="3.3" id="changes-from-r5-to-r6-from-lewg-telcon"><span class="header-section-number">3.3</span> Changes from R5 to R6 (from
LEWG telcon)<a href="#changes-from-r5-to-r6-from-lewg-telcon" class="self-link"></a></h2>
<ul>
<li>Defined <code class="sourceCode cpp">max_align_v</code> as <code class="sourceCode cpp"><span class="kw">inline</span> <span class="kw">constexpr</span></code>.</li>
<li>Removed nested <code class="sourceCode cpp">type</code> from
<code class="sourceCode cpp">aligned_raw_storage</code>. Made it clear
that <code class="sourceCode cpp">aligned_raw_storage</code> is not a
drop-in replacement for
<code class="sourceCode cpp">aligned_storage</code>.</li>
<li>Removed <code class="sourceCode cpp">aligned_object_storage</code>,
which was not needed for this proposal, from the formal wording. This
facility might come back in a separate paper.</li>
<li>Changed ship vehicle to C++26.</li>
</ul>
<h2 data-number="3.4" id="changes-from-r4-to-r5-from-lwg-reflector-discussion"><span class="header-section-number">3.4</span> Changes from R4 to R5 (from LWG
reflector discussion)<a href="#changes-from-r4-to-r5-from-lwg-reflector-discussion" class="self-link"></a></h2>
<ul>
<li>Mandate that <code class="sourceCode cpp">T</code> for <code class="sourceCode cpp">aligned_object_storage<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
must be an object type.</li>
<li>Clarify that <code class="sourceCode cpp">T</code> for <code class="sourceCode cpp">aligned_object_storage<span class="op">&lt;</span>T<span class="op">&gt;</span></code>
may be cv-qualified.</li>
<li>Change LFTS reference from v2 to v3.</li>
</ul>
<h2 data-number="3.5" id="changes-from-r3-to-r4-from-lwg-telcon"><span class="header-section-number">3.5</span> Changes from R3 to R4 (from LWG
telcon)<a href="#changes-from-r3-to-r4-from-lwg-telcon" class="self-link"></a></h2>
<ul>
<li>Added <em><a href="#design-changes-for-lewg-review">Design
changes</a></em> section that describes changes after LWG review.</li>
<li>Added <code class="sourceCode cpp">MaxType</code> as a second
template parameter to <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>.</li>
<li>Added the <code class="sourceCode cpp">max_align_v</code> constant,
<code class="sourceCode cpp">aligned_type</code> metafunction,
<code class="sourceCode cpp">aligned_raw_storage</code> class template,
and <code class="sourceCode cpp">aligned_object_storage</code> class
template.</li>
<li>Made a few editorial changes to comply with LWG style.</li>
</ul>
<h2 data-number="3.6" id="changes-from-r2-to-r3-in-kona-and-pre-cologne"><span class="header-section-number">3.6</span> Changes from R2 to R3 (in Kona
and pre-Cologne)<a href="#changes-from-r2-to-r3-in-kona-and-pre-cologne" class="self-link"></a></h2>
<ul>
<li>Changed <strong><code class="sourceCode cpp">resource<span class="op">-</span>adaptor<span class="op">-</span>imp</code></strong>
to kabob case.</li>
<li>Removed special member functions (copy/move ctors, etc.) and let
them be auto-generated.</li>
<li>Added a requirement that the
<code class="sourceCode cpp">Allocator</code> template parameter must
support rebinding to any non-class, non-over-aligned type. This allows
the implementation of <code class="sourceCode cpp">do_allocate</code> to
dispatch to a suitably rebound copy of the allocator as needed to
support any native alignment argument.</li>
</ul>
<h2 data-number="3.7" id="changes-from-r1-to-r2-in-san-diego"><span class="header-section-number">3.7</span> Changes from R1 to R2 (in San
Diego)<a href="#changes-from-r1-to-r2-in-san-diego" class="self-link"></a></h2>
<ul>
<li>Paper was forwarded from LEWG to LWG on Tuesday, 2018-10-06</li>
<li>Copied the formal wording from the LFTS directly into this
paper</li>
<li>Minor wording changes as per initial LWG review</li>
<li>Rebased to the October 2018 draft of the C++ WP</li>
</ul>
<h2 data-number="3.8" id="changes-from-r0-to-r1-pre-san-diego"><span class="header-section-number">3.8</span> Changes from R0 to R1 (pre-San
Diego)<a href="#changes-from-r0-to-r1-pre-san-diego" class="self-link"></a></h2>
<ul>
<li>Added a note for LWG to consider clarifying the alignment
requirements for <code class="sourceCode cpp">resource_adaptor<span class="op">&lt;</span>A<span class="op">&gt;::</span>do_allocate<span class="op">()</span></code>.</li>
<li>Changed rebind type from
<code class="sourceCode cpp"><span class="dt">char</span></code> to
<code class="sourceCode cpp">byte</code>.</li>
<li>Rebased to July 2018 draft of the C++ WP.</li>
</ul>
<h1 data-number="4" id="motivation"><span class="header-section-number">4</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>It is expected that more and more classes, especially those that
would not otherwise be templates, will use <code class="sourceCode cpp">pmr<span class="op">::</span>polymorphic_allocator<span class="op">&lt;</span>byte<span class="op">&gt;</span></code>
to allocate memory rather than specifying an allocator as a template
parameter. In order to pass an allocator to one of these classes, the
allocator must either already be a polymorphic allocator, or must be
adapted from a non-polymorphic allocator. The process of adaptation is
facilitated by <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>,
which is a simple class template, has been in the LFTS for a long time,
and has been fully implemented. It is therefore a low-risk, high-benefit
component to add to the C++ WP.</p>
<h1 data-number="5" id="summary-of-proposal"><span class="header-section-number">5</span> Summary of Proposal<a href="#summary-of-proposal" class="self-link"></a></h1>
<p>The central new class template in this proposal is <code class="sourceCode cpp">std<span class="op">::</span>pmr<span class="op">::</span>resource_adaptor</code>,
which wraps a class meeting the <em>Cpp17Allocator</em> requirements
with a class derived from <code class="sourceCode cpp">std<span class="op">::</span>pmr<span class="op">::</span>memory_resource</code>.
Consider an allocator-aware class
<code class="sourceCode cpp">Employee</code> that is not a template and
therefore has no <code class="sourceCode cpp">Allocator</code> template
parameter. Instead an <code class="sourceCode cpp">Employee</code> uses
<code class="sourceCode cpp">std<span class="op">::</span>pmr<span class="op">::</span>polymorphic_allocator</code>
using the standard idiom:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> Employee</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>  std<span class="op">::</span>pmr<span class="op">::</span>string m_name;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">unsigned</span>         m_id;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> allocator_type <span class="op">=</span> std<span class="op">::</span>pmr<span class="op">::</span>polymorphic_allocator<span class="op">&lt;&gt;</span>;</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  Employee<span class="op">(</span>std<span class="op">::</span>string_view name, <span class="dt">unsigned</span> id, <span class="kw">const</span> allocator_type<span class="op">&amp;</span> alloc <span class="op">=</span> <span class="op">{})</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">:</span> m_name<span class="op">(</span>name, alloc<span class="op">)</span>, m_id<span class="op">(</span>id<span class="op">)</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ..</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a>  allocator_type get_allocator<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> m_name<span class="op">.</span>get_allocator<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>There also exists a useful allocator,
<code class="sourceCode cpp">MyAlloc</code>, that conforms to the
allocator requirements:</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">class</span> MyAlloc</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> value_type <span class="op">=</span> T;</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  MyAlloc<span class="op">(</span><span class="dt">void</span><span class="op">*</span> baseptr<span class="op">)</span>;  <span class="co">// arbitrary ctor parameter for illustration</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  T<span class="op">*</span> allocate<span class="op">(</span>std<span class="op">::</span><span class="dt">size_t</span> n<span class="op">)</span>;</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>  <span class="dt">void</span> deallocate<span class="op">(</span>T<span class="op">*</span> p, std<span class="op">::</span><span class="dt">size_t</span> n<span class="op">)</span>;</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ...</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>One can pass a <code class="sourceCode cpp">MyAlloc</code> object as
an allocator to <code class="sourceCode cpp">Employee</code> by wrapping
it in <code class="sourceCode cpp">resource_adaptor</code>:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">using</span> MyAllocRsrc <span class="op">=</span> std<span class="op">::</span>pmr<span class="op">::</span>resource_adaptor<span class="op">&lt;</span>MyAlloc<span class="op">&lt;</span><span class="dt">char</span><span class="op">&gt;&gt;</span>;</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>MyAllocRsrc theRsrc<span class="op">(</span>getBasePtr<span class="op">())</span>;     <span class="co">// Ctor argument for wrapped allocator</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>Employee e<span class="op">(</span><span class="st">&quot;Superman&quot;</span>, <span class="dv">99</span>, <span class="op">&amp;</span>theRsrc<span class="op">)</span>;  <span class="co">// Pass allocator to `Employee`</span></span></code></pre></div>
<p>In addition to <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>,
this paper proposes:</p>
<ul>
<li><code class="sourceCode cpp">max_align_v</code>: an alias for <code class="sourceCode cpp"><span class="kw">alignof</span><span class="op">(</span>max_align_t<span class="op">)</span></code></li>
<li><code class="sourceCode cpp">aligned_raw_storage<span class="op">&lt;</span>Align, Size<span class="op">&gt;</span></code>:
a buffer of bytes having the specified alignment and minimum size</li>
<li><code class="sourceCode cpp">aligned_type<span class="op">&lt;</span>Align<span class="op">&gt;</span></code>:
a metafunction returning a type with the specified alignment</li>
</ul>
<p>These additions are needed to cleanly specify <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>,
but are also useful in their own right.</p>
<h1 data-number="6" id="design-changes-r6-to-current-for-lewg-review"><span class="header-section-number">6</span> Design changes R6 to current (for
LEWG review)<a href="#design-changes-r6-to-current-for-lewg-review" class="self-link"></a></h1>
<p>The following design changes were made as a consequence of
discussions in LWG on 5 October 2021. LWG felt that the scope of these
changes warranted review by LEWG.</p>
<p><strong><code class="sourceCode cpp">MaxAlign</code> template
argument</strong>: A <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>
instance wraps an object having a type that meets the Allocator
requirements. Its <code class="sourceCode cpp">do_allocate</code>
virtual member function supplies aligned memory by invoking the
<code class="sourceCode cpp">allocate</code> member function on the
wrapped allocator. The only way to supply alignment information to the
wrapped allocator is to rebind it for a
<code class="sourceCode cpp">value_type</code> having the desired
alignment but, because the alignment is specified to <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor<span class="op">::</span>allocate</code>
at run time, the implementation must rebind its allocator for every
possible alignment and dynamically choose the correct one. In order to
keep the number of such rebound instantiations manageable and reduce the
requirements on the allocator type, an upper limit (default <code class="sourceCode cpp"><span class="kw">alignof</span><span class="op">(</span>max_align_t<span class="op">)</span></code>)
can be specified when instantiating <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>.
This recent change was made after discussion with members of LWG, and
with their encouragement.</p>
<p><strong>(Optional)
<code class="sourceCode cpp"><span class="kw">constexpr</span></code>
value <code class="sourceCode cpp">max_align_v</code></strong>: The
standard has a type, <code class="sourceCode cpp">std<span class="op">::</span>max_align_t</code>,
whose alignment is at least as great as that of every scalar type. I
found that I was continually referring to the <em>value</em>, <code class="sourceCode cpp"><span class="kw">alignof</span><span class="op">(</span>std<span class="op">::</span>max_align_t<span class="op">)</span></code>.
In fact, <em>every single use</em> of
<code class="sourceCode cpp">max_align_t</code> in the standard is as
the operand of
<code class="sourceCode cpp"><span class="kw">alignof</span></code>. As
a drive-by fix, therefore, this proposal introduces the constant
<code class="sourceCode cpp">max_align_v</code> as a more
straightforward spelling of <code class="sourceCode cpp"><span class="kw">alignof</span><span class="op">(</span>max_align_t<span class="op">)</span></code>.
Note that the introduction of this constant is completely severable from
the proposal if it is deemed undesirable. The name is also subject to
bikeshedding (e.g., by removing the
<code class="sourceCode cpp">_v</code>).</p>
<p><strong>Alias template <code class="sourceCode cpp">std<span class="op">::</span>aligned_type</code></strong>:
This alias is effectively a metafunction that resolves to a scalar type
if possible, otherwise to a specialization of
<code class="sourceCode cpp">aligned_raw_storage</code>. Its use in this
specification allows <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>
to work with minimalist allocators, including those that can be rebound
only for scalar types. For over-aligned values, it uses
<code class="sourceCode cpp">aligned_raw_storage</code>, below. Both
<code class="sourceCode cpp">aligned_raw_storage</code> and
<code class="sourceCode cpp">aligned_type</code> are declared in header
<code class="sourceCode cpp"><span class="op">&lt;</span>memory<span class="op">&gt;</span></code>,
but LEWG could consider putting them somewhere else (e.g., in <code class="sourceCode cpp"><span class="op">&lt;</span>utility<span class="op">&gt;</span></code>).</p>
<p><strong>Class template <code class="sourceCode cpp">std<span class="op">::</span>aligned_raw_storage</code></strong>:
When instantiated with an alignment greater than
<code class="sourceCode cpp">max_align_v</code>, <code class="sourceCode cpp">std<span class="op">::</span>aligned_type</code>
could be defined vaguely in terms of an unspecified over-aligned type,
but LWG wanted to be more precise so as to better describe the allowable
set of allocators usable with
<code class="sourceCode cpp">resource_adaptor</code>. The obvious choice
of the over-aligned type would have been <code class="sourceCode cpp">std<span class="op">::</span>aligned_storage</code>,
but that template has been deprecated as a result of numerous flaws
described in <span class="citation" data-cites="P1413R3">[<a href="https://wg21.link/p1413r3" role="doc-biblioref">P1413R3</a>]</span>. The class template <code class="sourceCode cpp">std<span class="op">::</span>aligned_raw_storage</code>
is intended to replace <code class="sourceCode cpp">std<span class="op">::</span>aligned_storage</code>
and correct the problems associated with it; specifically, it is not a
metafunction, but a
<code class="sourceCode cpp"><span class="kw">struct</span></code>
template, and it provides direct access to its data buffer, which can be
validly cast to a pointer to any type having the specified alignment (or
less). The relationship between size and alignment is specifically
described in the wording, so programmers can rely on it. Note that
<code class="sourceCode cpp">aligned_raw_storage</code> is not a drop-in
replacement for the deprecated
<code class="sourceCode cpp">aligned_storage</code> metafunction because
the arguments are reversed and it does not provide a
<code class="sourceCode cpp">type</code> member typedef.</p>
<p><strong>(Not proposed) Class template <code class="sourceCode cpp">std<span class="op">::</span>aligned_object_storage</code></strong>:
The alignment parameter for
<code class="sourceCode cpp">aligned_raw_storage</code>, described
above, is specified as a number rather than as a type – as needed for
low-level types like <code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>
– and the storage must be cast to the desired type before it’s used.
This primitive type practically screams for the introduction of an
aligned storage type parameterized on the type of object you wish to
store in it. Although not needed for this proposal, prior revisions of
this proposal included
<code class="sourceCode cpp">aligned_object_storage</code> for this
purpose. However, because of technical concerns regarding the design of
<code class="sourceCode cpp">aligned_object_storage</code>, it was
decided that it would be best to split it out into its own paper so that
it could be refined (or rejected) separately, without affecting this
proposal.</p>
<h1 data-number="7" id="impact-on-the-standard"><span class="header-section-number">7</span> Impact on the standard<a href="#impact-on-the-standard" class="self-link"></a></h1>
<p><code class="sourceCode cpp">pmr<span class="op">::</span>resource_adaptor</code>
is a pure library extension requiring no changes to the core language
nor to any existing classes in the standard library. A couple of
general-purpose templates
(<code class="sourceCode cpp">aligned_type</code> and
<code class="sourceCode cpp">aligned_raw_storage</code>) are also added
as pure library extensions.</p>
<h1 data-number="8" id="implementation-experience"><span class="header-section-number">8</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>A full implementation of the current proposal can be found in GitHub
at <a href="https://github.com/phalpern/WG21-halpern/tree/P1083/P1083-resource_adaptor">https://github.com/phalpern/WG21-halpern/tree/P1083/P1083-resource_adaptor</a>.</p>
<p>The version described in the Library Fundamentals TS has been
implemented by multiple vendors in the <code class="sourceCode cpp">std<span class="op">::</span>experimental<span class="op">::</span>pmr</code>
namespace.</p>
<h1 data-number="9" id="formal-wording"><span class="header-section-number">9</span> Formal Wording<a href="#formal-wording" class="self-link"></a></h1>
<p><em>This proposal is based on the Library Fundamentals TS v3 <span class="citation" data-cites="N4873">[<a href="https://wg21.link/n4873" role="doc-biblioref">N4873</a>]</span> and the April 2024 draft of the
C++ WP <span class="citation" data-cites="N4981">[<a href="https://wg21.link/n4981" role="doc-biblioref">N4981</a>]</span></em>.</p>
<p>In <span>17.2.1
<a href="https://wg21.link/N4981#cstddef.syn">[cstddef.syn]</a><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></span>, add the following definition
sometime after the declaration of
<code class="sourceCode cpp">max_align_t</code> in header <code class="sourceCode cpp"><span class="op">&lt;</span>cstddef<span class="op">&gt;</span></code>:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="line-block"><code class="sourceCode default">inline constexpr size_t max_align_v = alignof(max_align_t);</code></div>
</blockquote>

</div>
<p>In section <span>20.2.2
<a href="https://wg21.link/N4981#memory.syn">[memory.syn]</a></span>,
add the following declarations to <code class="sourceCode cpp"><span class="op">&lt;</span>memory<span class="op">&gt;</span></code>
(probably near the top, between <em>pointer alignment</em> and
<em>explicit lifetime management</em>):</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="line-block"><code class="sourceCode default">template &lt;size_t Align, size_t Sz = Align&gt; struct aligned_raw_storage;</code><br />
<code class="sourceCode default">template &lt;size_t Align&gt; using aligned_type =</code>
<em>see below</em><code class="sourceCode default">;</code></div>
</blockquote>

</div>
<p>Insert within <span>20.2.5
<a href="https://wg21.link/N4981#ptr.align">[ptr.align]</a></span> and
<span>20.2.6
<a href="https://wg21.link/N4981#obj.lifetime">[obj.lifetime]</a></span>
the description of these new templates:</p>
<div class="add" style="color: #006e28">

<blockquote>
<p><strong>20.2.? Aligned storage [aligned.storage]</strong></p>
</blockquote>
<blockquote>
<p><strong>20.2.?.1 Aligned raw storage
[aligned.raw.storage]</strong></p>
</blockquote>
<blockquote>
<p>An instantiation of template
<code class="sourceCode default">aligned_raw_storage</code> is a
standard-layout trivial type that provides storage having the specified
alignment and size, where the size is rounded up to the nearest multiple
of the alignment. The program is ill-formed unless
<code class="sourceCode default">Align</code> is a power of 2.</p>
</blockquote>
<blockquote>
<div class="sourceCode" id="cb4"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>namespace std {</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>  template &lt;size_t Align, size_t Sz = Align&gt;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>  struct aligned_raw_storage</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  {</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    static constexpr size_t alignment = Align;</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    static constexpr size_t size      = (Sz + Align - 1) &amp; ~(Align - 1);</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    constexpr       void* data()       noexcept { return buffer; }</span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>    constexpr const void* data() const noexcept { return buffer; }</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a>    alignas(alignment) byte buffer[size];</span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>  };</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
</blockquote>
<blockquote>
<p><strong>20.2.?.3 Aligned type [aligned.type]</strong></p>
</blockquote>
<blockquote>
<p>Instantiating
<code class="sourceCode default">aligned_type&lt;Align&gt;</code> yields
a type <code class="sourceCode default">T</code>, such that
<code class="sourceCode default">alignof(T) == Align</code> and
<code class="sourceCode default">sizeof(T) == Align</code> If there
exists a scalar type, meeting these requirements, then
<code class="sourceCode default">aligned_type&lt;Align&gt;</code> is an
alias for that scalar type; otherwise, it is an alias for <code class="sourceCode default">aligned_raw_storage&lt;Align, Align&gt;</code>.
If more than one scalar meets the requirements for
<code class="sourceCode default">T</code>, the one chosen is
implementation defined, but consistent for all instantiations of
<code class="sourceCode default">aligned_type</code> with that
alignment. The program is ill-formed unless
<code class="sourceCode default">Align</code> is a power of 2.</p>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode default">template &lt;size_t Align&gt; using aligned_type =</code>
<em>see below</em>;</div>
</blockquote>

</div>
<p>In <span>20.4.1
<a href="https://wg21.link/N4981#mem.res.syn">[mem.res.syn]</a></span>,
add the following declaration immediately after the declaration of <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">!=(</span><span class="kw">const</span> polymorphic_allocator<span class="op">...)</span></code>:</p>
<div class="add" style="color: #006e28">

<blockquote>
<div class="sourceCode" id="cb5"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>// 20.4.? resource adaptor for a given alignment.</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>// The name <em>resource-adaptor-imp</em> is for exposition only.</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>template &lt;class Allocator, size_t MaxAlign&gt; class <em>resource-adaptor-imp</em>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>template &lt;class Allocator, size_t MaxAlign = max_align_v&gt;</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a> using resource_adaptor = <em>resource-adaptor-imp</em>&lt;</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    typename allocator_traits&lt;Allocator&gt;::template rebind_alloc&lt;byte&gt;,</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>    MaxAlign&gt;;</span></code></pre></div>
</blockquote>

</div>
<p>Before section <span>20.4.5
<a href="https://wg21.link/N4981#mem.res.pool">[mem.res.pool]</a></span>,
insert the following section, taken with modifications from section 5.5
of the LFTS v3:</p>
<div class="add" style="color: #006e28">

<blockquote>
<p><strong>20.4.? Alias template resource_adaptor
[memory.resource.adaptor]</strong></p>
</blockquote>
<blockquote>
<p><strong>20.4.?.1
<code class="sourceCode default">resource_adaptor</code>
[memory.resource.adaptor.overview]</strong></p>
</blockquote>
<blockquote>
<p>An instance of <code class="sourceCode default">resource_adaptor&lt;Allocator, MaxAlign&gt;</code>
is an adaptor that wraps a
<code class="sourceCode default">memory_resource</code> interface around
<code class="sourceCode default">Allocator</code>. [<em>Note</em>: The
type of
<code class="sourceCode default">resource_adaptor&lt;X, N&gt;</code> is
independent of <code class="sourceCode default">X::value_type</code>. –
<em>end note</em>] The Allocator parameter to resource_adaptor shall
meet the <em>Cpp17Allocator</em> requirements (<span>16.4.4.6.1
<a href="https://wg21.link/N4981#allocator.requirements.general">[allocator.requirements.general]</a></span>).
The program is ill-formed if any of</p>
</blockquote>
<blockquote>
<ul>
<li><code class="sourceCode default">is_same_v&lt;typename allocator_traits&lt;Allocator&gt;::pointer,    allocator_traits&lt;Allocator&gt;::value_type*&gt;</code>,</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li><code class="sourceCode default">is_same_v&lt;typename allocator_traits&lt;Allocator&gt;::const_pointer, const    allocator_traits&lt;Allocator&gt;::value_type*&gt;</code>,</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li><code class="sourceCode default">is_same_v&lt;typename allocator_traits&lt;Allocator&gt;::void_pointer, void*&gt;</code>,
or</li>
</ul>
</blockquote>
<blockquote>
<ul>
<li><code class="sourceCode default">is_same_v&lt;typename allocator_traits&lt;Allocator&gt;::const_void_pointer,    const void*&gt;</code></li>
</ul>
</blockquote>
<blockquote>
<p>is false. The program is ill-formed, no diagnostic required, unless
calls to <code class="sourceCode default">allocator_traits&lt;Allocator&gt;::template rebind_traits&lt;aligned_type&lt;N&gt;&gt;::allocate</code>
and <code class="sourceCode default">allocator_traits&lt;Allocator&gt;::template rebind_traits&lt;aligned_type&lt;N&gt;&gt;::deallocate</code>
are well-formed for all <code class="sourceCode default">N</code>, such
that <code class="sourceCode default">N</code> is a power of 2 less than
or equal to <code class="sourceCode default">MaxAlign</code>.</p>
</blockquote>
<blockquote>
<div class="sourceCode" id="cb6"><pre class="sourceCode default cpp"><code class="sourceCode default"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>// The name &quot;<em>resource-adaptor-imp</em>&quot; is for exposition only.</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>template &lt;class Allocator, size_t MaxAlign&gt;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>class <em>resource-adaptor-imp</em> : public memory_resource {</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  Allocator m_alloc; // exposition only</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>public:</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  using adapted_allocator_type = Allocator;</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>  resource-adaptor-imp() = default;</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>  resource-adaptor-imp(const resource-adaptor-imp&amp;) noexcept = default;</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>  resource-adaptor-imp(resource-adaptor-imp&amp;&amp;) noexcept = default;</span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>  explicit resource-adaptor-imp(const Allocator&amp; a2) noexcept;</span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>  explicit resource-adaptor-imp(Allocator&amp;&amp; a2) noexcept;</span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>  template &lt;class... Args&gt;</span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>    explicit resource_adaptor_imp(Args&amp;&amp;... args);</span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>  resource-adaptor-imp&amp; operator=(const resource-adaptor-imp&amp;) = default;</span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a>  adapted_allocator_type get_adapted_allocator() const noexcept</span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a>  {</span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>    return m_alloc;</span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a>protected:</span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a>  void* do_allocate(size_t bytes, size_t alignment) override;</span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a>  void do_deallocate(void* p, size_t bytes, size_t alignment) override;</span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true" tabindex="-1"></a>  bool do_is_equal(const memory_resource&amp; other) const noexcept override;</span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true" tabindex="-1"></a>};</span></code></pre></div>
</blockquote>
<blockquote>
<p><strong>20.4.?.2
<code class="sourceCode default">resource-adaptor-imp</code>
constructors [memory.resource.adaptor.ctor]</strong></p>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode default">explicit <em>resource-adaptor-imp</em>(const Allocator&amp; a2) noexcept;</code></div>
</blockquote>
<blockquote>
<blockquote>
<p><em>Effects</em>: Initializes
<code class="sourceCode default">m_alloc</code> with
<code class="sourceCode default">a2</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode default">explicit <em>resource-adaptor-imp</em>(Allocator&amp;&amp; a2) noexcept;</code></div>
</blockquote>
<blockquote>
<blockquote>
<p><em>Effects</em>: Initializes
<code class="sourceCode default">m_alloc</code> with
<code class="sourceCode default">std::move(a2)</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode default">template &lt;class... Args&gt;</code><br />
   <code class="sourceCode default">explicit <em>resource_adaptor_imp</em>(Args&amp;&amp;... args);</code></div>
</blockquote>
<blockquote>
<blockquote>
<p><em>Constraints</em>: <code class="sourceCode default">is_constructible_v&lt;Allocator, Args...&gt;</code>
is true.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Effects</em>: Initializes
<code class="sourceCode default">m_alloc</code> with <code class="sourceCode default">std::forward&lt;Args&gt;(args)...</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<p><strong>20.4.?.3
<code class="sourceCode default">resource-adaptor-imp</code> member
functions [memory.resource.adaptor.mem]</strong></p>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode default">void* do_allocate(size_t bytes, size_t alignment);</code></div>
</blockquote>
<blockquote>
<blockquote>
<p>Let <code class="sourceCode default">CA</code> be an integral
constant expression such that
<code class="sourceCode default">CA == alignment</code>, is
<code class="sourceCode default">true</code>, let
<code class="sourceCode default">U</code> be the type
<code class="sourceCode default">aligned_type&lt;CA&gt;</code>, and let
<code class="sourceCode default">n</code> be <code class="sourceCode default">(bytes + sizeof(U) - 1) / sizeof(U)</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Preconditions:</em>
<code class="sourceCode default">alignment</code> is a power of two.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Returns:</em> <code class="sourceCode default">allocator_traits&lt;Allocator&gt;::template</code>
<code class="sourceCode default">rebind_traits&lt;U&gt;::allocate(m_alloc, n)</code></p>
</blockquote>
</blockquote>
<blockquote>
<p><em>Throws:</em> nothing unless the underlying allocator throws.</p>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode default">void do_deallocate(void* p, size_t bytes, size_t alignment);</code></div>
</blockquote>
<blockquote>
<blockquote>
<p>Let <code class="sourceCode default">CA</code> be an integral
constant expression such that
<code class="sourceCode default">CA == alignment</code>, is
<code class="sourceCode default">true</code>, let
<code class="sourceCode default">U</code> be the type
<code class="sourceCode default">aligned_type&lt;CA&gt;</code>, and let
<code class="sourceCode default">n</code> be <code class="sourceCode default">(bytes + sizeof(U) - 1) / sizeof(U)</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Preconditions</em>: given a memory resource
<code class="sourceCode default">r</code> such that
<code class="sourceCode default">this-&gt;is_equal(r)</code> is
<code class="sourceCode default">true</code>,
<code class="sourceCode default">p</code> was returned from a prior call
to <code class="sourceCode default">r.allocate(bytes, alignment)</code>
and the storage at <code class="sourceCode default">p</code> has not yet
been deallocated.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Effects:</em> <code class="sourceCode default">allocator_traits&lt;Allocator&gt;::template rebind_traits&lt;U&gt;::deallocate(m_alloc, p, n)</code></p>
</blockquote>
</blockquote>
<blockquote>
<div class="line-block"><code class="sourceCode default">bool do_is_equal(const memory_resource&amp; other) const noexcept;</code></div>
</blockquote>
<blockquote>
<blockquote>
<p>Let <code class="sourceCode default">p</code> be <code class="sourceCode default">dynamic_cast&lt;const <em>resource-adaptor-imp</em>*&gt;(&amp;other)</code>.</p>
</blockquote>
</blockquote>
<blockquote>
<blockquote>
<p><em>Returns</em>: <code class="sourceCode default">false</code> if
<code class="sourceCode default">p</code> is null; otherwise the value
of <code class="sourceCode default">m_alloc == p-&gt;m_alloc</code>.</p>
</blockquote>
</blockquote>

</div>
<h1 data-number="10" id="bibliography"><span class="header-section-number">10</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body hanging-indent" data-entry-spacing="1" role="doc-bibliography">
<div id="ref-N4873" class="csl-entry" role="doc-biblioentry">
[N4873] Thomas Köppe. 2020-11-09. Working Draft, C++ Extensions for
Library Fundamentals, Version 3. <a href="https://wg21.link/n4873"><div class="csl-block">https://wg21.link/n4873</div></a>
</div>
<div id="ref-N4981" class="csl-entry" role="doc-biblioentry">
[N4981] Thomas Köppe. 2024-04-16. Working Draft, Programming Languages —
C++. <a href="https://wg21.link/n4981"><div class="csl-block">https://wg21.link/n4981</div></a>
</div>
<div id="ref-P1083R5" class="csl-entry" role="doc-biblioentry">
[P1083R5] Pablo Halpern. 2022-02-24. Move resource_adaptor from Library
TS to the C++ WP. <a href="https://wg21.link/p1083r5"><div class="csl-block">https://wg21.link/p1083r5</div></a>
</div>
<div id="ref-P1413R3" class="csl-entry" role="doc-biblioentry">
[P1413R3] CJ Johnson. 2021-11-22. Deprecate std::aligned_storage and
std::aligned_union. <a href="https://wg21.link/p1413r3"><div class="csl-block">https://wg21.link/p1413r3</div></a>
</div>
</div>
<section class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>All citations to the Standard are to
working draft N4981 unless otherwise specified.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>
