<!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="2022-03-15" />
  <title>mdarray: An Owning Multidimensional Array Analog of mdspan</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%;}
  </style>
  <style>
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: #6.0e28}
code.diff span.st {color: #bf0303}
  </style>
  <style type="text/css">
body {
margin: 5em;
font-family: serif;

hyphens: auto;
line-height: 1.35;
}
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; }

div#refs p { padding-left: 32px; text-indent: -32px; }
</style>
  <link href="data:image/vnd.microsoft.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"><code>mdarray</code>: An
Owning Multidimensional Array Analog of <code>mdspan</code></h1>

<table style="border:none;float:right">
  <tr>
    <td>Document #: </td>
    <td>P1684R1</td>
  </tr>
  <tr>
    <td>Date: </td>
    <td>2022-03-15</td>
  </tr>
  <tr>
    <td style="vertical-align:top">Project: </td>
    <td>Programming Language C++<br>
      Library Evolution<br>
    </td>
  </tr>
  <tr>
    <td style="vertical-align:top">Reply-to: </td>
    <td>
      Christian Trott<br>&lt;<a href="mailto:crtrott@sandia.gov" class="email">crtrott@sandia.gov</a>&gt;<br>
      David Hollman<br>&lt;<a href="mailto:me@dsh.fyi" class="email">me@dsh.fyi</a>&gt;<br>
      Mark Hoemmen<br>&lt;<a href="mailto:mhoemmen@stellarscience.com" class="email">mhoemmen@stellarscience.com</a>&gt;<br>
      Daniel Sunderland<br>&lt;<a href="mailto:dansunderland@gmail.com" class="email">dansunderland@gmail.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="#revision-history"><span class="toc-section-number">1</span> Revision History<span></span></a>
<ul>
<li><a href="#p1684r1-2022-03-mailing"><span class="toc-section-number">1.1</span> P1684r1: 2022-03
Mailing<span></span></a></li>
</ul></li>
<li><a href="#motivation"><span class="toc-section-number">2</span>
Motivation<span></span></a></li>
<li><a href="#design"><span class="toc-section-number">3</span>
Design<span></span></a>
<ul>
<li><a href="#design-overview"><span class="toc-section-number">3.1</span> Design
Overview<span></span></a></li>
<li><a href="#principal-differences-between-mdarray-and-mdspan"><span class="toc-section-number">3.2</span> Principal Differences between
<code>mdarray</code> and <code>mdspan</code><span></span></a></li>
<li><a href="#extents-design-reused"><span class="toc-section-number">3.3</span> <code>Extents</code> Design
Reused<span></span></a></li>
<li><a href="#layoutpolicy-design-reused"><span class="toc-section-number">3.4</span> <code>LayoutPolicy</code> Design
Reused<span></span></a></li>
<li><a href="#accessorpolicy-replaced-by-container"><span class="toc-section-number">3.5</span> <code>AccessorPolicy</code>
Replaced by <code>Container</code><span></span></a>
<ul>
<li><a href="#expected-behavior-of-motivating-use-cases"><span class="toc-section-number">3.5.1</span> Expected Behavior of Motivating
Use Cases<span></span></a></li>
<li><a href="#analogs-in-the-standard-library-container-adapters"><span class="toc-section-number">3.5.2</span> Analogs in the Standard Library:
Container Adapters<span></span></a></li>
<li><a href="#not-proposed-alternative-a-dedicated-containerpolicy-concept"><span class="toc-section-number">3.5.3</span> (Not Proposed) Alternative: A
Dedicated <code>ContainerPolicy</code> Concept<span></span></a></li>
<li><a href="#not-proposed-alternative-containerpolicy-subsumes-accessorpolicy"><span class="toc-section-number">3.5.4</span> (Not Proposed) Alternative:
<code>ContainerPolicy</code> subsumes
<code>AccessorPolicy</code><span></span></a></li>
</ul></li>
</ul></li>
<li><a href="#wording"><span class="toc-section-number">4</span>
Wording<span></span></a></li>
<li><a href="#references"><span class="toc-section-number">5</span>
References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" id="revision-history"><span class="header-section-number">1</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<h2 data-number="1.1" id="p1684r1-2022-03-mailing"><span class="header-section-number">1.1</span> P1684r1: 2022-03 Mailing<a href="#p1684r1-2022-03-mailing" class="self-link"></a></h2>
<h4 data-number="1.1.0.1" id="changes-from-r0"><span class="header-section-number">1.1.0.1</span> Changes from R0<a href="#changes-from-r0" class="self-link"></a></h4>
<ul>
<li>harmonize with P0009R15</li>
<li>don’t use ContainerPolicy, simply use Container as fourth template
argument</li>
<li>added wording</li>
</ul>
<h1 data-number="2" id="motivation"><span class="header-section-number">2</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p><span class="citation" data-cites="P0009R9">[<a href="#ref-P0009R9" role="doc-biblioref">P0009R9</a>]</span> introduced a non-owning
multidimensional array abstraction that has been refined over many
revisions and is expected to be merged into the C++ working draft early
in the C++23 cycle. However, there are many owning use cases where
<code>mdspan</code> is not ideal. In particular, for use cases with
small, fixed-size dimensions, the non-owning semantics of
<code>mdspan</code> may represent a significant pessimization,
precluding optimizations that arise from the removal of the non-owning
indirection (such as storing the data in registers).</p>
<p>Without <code>mdarray</code>, use cases that should be owning are
awkward to express:</p>
<p><strong>P0009 Only:</strong></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> make_random_rotation<span class="op">(</span>mdspan<span class="op">&lt;</span><span class="dt">float</span>, <span class="dv">3</span>, <span class="dv">3</span><span class="op">&gt;</span> output<span class="op">)</span>;</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> apply_rotation<span class="op">(</span>mdspan<span class="op">&lt;</span><span class="dt">float</span>, <span class="dv">3</span>, <span class="dv">3</span><span class="op">&gt;</span>, mdspan<span class="op">&lt;</span><span class="dt">float</span>, <span class="dv">3</span><span class="op">&gt;)</span>;</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> random_rotate<span class="op">(</span>mdspan<span class="op">&lt;</span><span class="dt">float</span>, dynamic_extent, <span class="dv">3</span><span class="op">&gt;</span> points<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="dt">float</span> buffer<span class="op">[</span><span class="dv">9</span><span class="op">]</span> <span class="op">=</span> <span class="op">{</span> <span class="op">}</span>;</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> rotation <span class="op">=</span> mdspan<span class="op">&lt;</span><span class="dt">float</span>, <span class="dv">3</span>, <span class="dv">3</span><span class="op">&gt;(</span>buffer<span class="op">)</span>;</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>  make_random_rotation<span class="op">(</span>rotation<span class="op">)</span>;</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">&lt;</span> points<span class="op">.</span>extent<span class="op">(</span><span class="dv">0</span><span class="op">)</span>; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    apply_rotation<span class="op">(</span>rotation, subspan<span class="op">(</span>points, i, std<span class="op">::</span>all<span class="op">))</span>;</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p><strong>This Work:</strong></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>mdarray<span class="op">&lt;</span><span class="dt">float</span>, <span class="dv">3</span>, <span class="dv">3</span><span class="op">&gt;</span> make_random_rotation<span class="op">()</span>;</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> apply_rotation<span class="op">(</span>mdarray<span class="op">&lt;</span><span class="dt">float</span>, <span class="dv">3</span>, <span class="dv">3</span><span class="op">&gt;&amp;</span>, <span class="kw">const</span> mdspan<span class="op">&lt;</span><span class="dt">float</span>, <span class="dv">3</span><span class="op">&gt;&amp;)</span>;</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> random_rotate<span class="op">(</span>mdspan<span class="op">&lt;</span><span class="dt">float</span>, dynamic_extent, <span class="dv">3</span><span class="op">&gt;</span> points<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> rotation <span class="op">=</span> make_random_rotation<span class="op">()</span>;</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>  <span class="cf">for</span><span class="op">(</span><span class="dt">int</span> i <span class="op">=</span> <span class="dv">0</span>; i <span class="op">&lt;</span> points<span class="op">.</span>extent<span class="op">(</span><span class="dv">0</span><span class="op">)</span>; <span class="op">++</span>i<span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    apply_rotation<span class="op">(</span>rotation, subspan<span class="op">(</span>points, i, std<span class="op">::</span>all<span class="op">))</span>;</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>Particularly for small, fixed-dimension <code>mdspan</code> use
cases, owning semantics can be a lot more convenient and require a lot
less in the way of interprocedural analysis to optimize.</p>
<h1 data-number="3" id="design"><span class="header-section-number">3</span> Design<a href="#design" class="self-link"></a></h1>
<p>One major goal of the design for <code>mdarray</code> is to parallel
the design of <code>mdspan</code> as much as possible (but no more),
with the goals of reducing cognitive load for users already familiar
with <code>mdspan</code> and of incorporating the lessons learned from
the half decade of experience on <span class="citation" data-cites="P0009R9">[<a href="#ref-P0009R9" role="doc-biblioref">P0009R9</a>]</span>. This paper (and this section
in particular) assumes the reader has read and is already familiar with
<span class="citation" data-cites="P0009R9">[<a href="#ref-P0009R9" role="doc-biblioref">P0009R9</a>]</span>.</p>
<h2 data-number="3.1" id="design-overview"><span class="header-section-number">3.1</span> Design Overview<a href="#design-overview" class="self-link"></a></h2>
<p>In brief, the analogy to <code>mdspan</code> can be seen in the
declaration of the proposed design for <code>mdarray</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">template</span><span class="op">&lt;</span><span class="kw">class</span> ElementType,</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> Extents,</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> LayoutPolicy <span class="op">=</span> layout_right,</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> Container <span class="op">=</span> <em>see-below</em><span class="op">&gt;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> mdarray;</span></code></pre></div>
<p>This intentionally parallels the design of <code>mdspan</code> in
<span class="citation" data-cites="P0009R9">[<a href="#ref-P0009R9" role="doc-biblioref">P0009R9</a>]</span>, which has the signature:</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><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ElementType,</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> Extents,</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> LayoutPolicy <span class="op">=</span> layout_right,</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> AccessorPolicy <span class="op">=</span> accessor_basic<span class="op">&lt;</span>ElementType<span class="op">&gt;&gt;</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">class</span> mdspan;</span></code></pre></div>
<p>Note that the original proposal for <code>mdarray</code> had a
<code>ContainerPolicy</code> instead of a <code>Container</code>
parameter. We decided that the complexity of a ContainerPolicy is not
actually required for <code>mdarray</code>. The vast majority of cases
where customization of the <code>AccessorPolicy</code> is required to
modify the access behavior, are local contextual requirements. For
example one has a loop with write conflicts, and wants an atomic
accessor. However, even with <code>mdarray</code> existing these
temporary objects need to be views of data, and thus one should create
an <code>mdspan</code> view with appropriate access behavior from the
<code>mdarray</code> which owns the data.</p>
<h2 data-number="3.2" id="principal-differences-between-mdarray-and-mdspan"><span class="header-section-number">3.2</span> Principal Differences between
<code>mdarray</code> and <code>mdspan</code><a href="#principal-differences-between-mdarray-and-mdspan" class="self-link"></a></h2>
<p>By design, <code>mdarray</code> is as similar as possible to
<code>mdspan</code>, except with container semantics instead of
reference semantics. However, the use of container semantics
necessitates a few differences. The most notable of these is deep
<code>const</code>ness. Like all reference semantic types in the
standard, <code>mdspan</code> has shallow <code>const</code>ness, but
container types in the standard library propagate <code>const</code>
through their access functions. Thus, <code>mdarray</code> needs
<code>const</code> and non-<code>const</code> versions of every
analogous operation in <code>mdspan</code> that interacts with the
underlying data:</p>
<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="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ElementType, <span class="kw">class</span> Extents, <span class="kw">class</span> LayoutPolicy, <span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> mdarray <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></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>  <span class="co">// also in mdspan:</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> pointer <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>  <span class="co">// only in mdarray:</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_pointer <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// also in mdspan:</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> reference <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a>  <span class="co">// only in mdarray:</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_reference <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// analogous to mdspan, except with const_reference return type:</span></span>
<span id="cb5-16"><a href="#cb5-16" 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> IndexType<span class="op">&gt;</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> const_reference <span class="kw">operator</span><span class="op">[](</span>IndexType<span class="op">...)</span> <span class="kw">const</span>;</span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> IndexType, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> const_reference <span class="kw">operator</span><span class="op">[](</span><span class="kw">const</span> array<span class="op">&lt;</span>IndexType, N<span class="op">&gt;&amp;)</span> <span class="kw">const</span>;</span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a>  <span class="co">// non-const overloads only in mdarray:</span></span>
<span id="cb5-21"><a href="#cb5-21" 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> IndexType<span class="op">&gt;</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> reference <span class="kw">operator</span><span class="op">[](</span>IndexType<span class="op">...)</span>;</span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> IndexType, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> reference <span class="kw">operator</span><span class="op">[](</span><span class="kw">const</span> array<span class="op">&lt;</span>IndexType, N<span class="op">&gt;&amp;)</span>;</span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a>  <span class="co">// also in mdspan, except with const_pointer return type:</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> const_pointer data<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true" tabindex="-1"></a>  <span class="co">// non-const overload only in mdarray:</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> pointer data<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Additionally, <code>mdarray</code> needs a means of interoperating
with <code>mdspan</code> in roughly the same way as contiguous
containers interact with <code>span</code>, or as <code>string</code>
interacts with <code>string_view</code>. We could do this by adding a
constructor to <code>mdspan</code>, which would be more consistent with
the analogous features in <code>span</code> and
<code>string_view</code>, but in the interest of avoiding modifications
to an in-flight proposal, we propose using a member function of
<code>mdarray</code> for this functionality for now (tentatively named
<code>view()</code>, subject to bikeshedding). We are happy to change
this based on design direction from LEWG:</p>
<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="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ElementType, <span class="kw">class</span> Extents, <span class="kw">class</span> LayoutPolicy, <span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> mdarray <span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// only in mdarray:</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> view_type <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_view_type <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>  view_type view<span class="op">()</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>  const_view_type view<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>As discussed below, <code>accessor_policy</code> from
<code>mdspan</code> is replaced by <code>container_policy</code> in
<code>mdarray</code>:</p>
<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="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ElementType, <span class="kw">class</span> Extents, <span class="kw">class</span> LayoutPolicy, <span class="kw">class</span> ContainerPolicy<span class="op">&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> mdarray <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// only in mdarray:</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> container_policy_type <span class="op">=</span> ContainerPolicy;</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> container_type <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h4 data-number="3.2.0.1" id="constructors-and-assignment-operators"><span class="header-section-number">3.2.0.1</span> Constructors and Assignment
Operators<a href="#constructors-and-assignment-operators" class="self-link"></a></h4>
<p>There are several relatively trivial differences between
<code>mdspan</code> and <code>mdarray</code> constructors and assignment
operators. Most trivially, <code>mdspan</code> provides a compatible
<code>mdspan</code> copy-like constructor and copy-like assignment
operator, with proper constraints and expectations to enforce
compatibility of shape, layout, and size. Since <code>mdarray</code> has
owning semantics, we also need move-like versions of these:</p>
<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="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ElementType, <span class="kw">class</span> Extents, <span class="kw">class</span> LayoutPolicy, <span class="kw">class</span> ContainerPolicy<span class="op">&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> mdarray <span class="op">{</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// analogous to mdspan:</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ET, <span class="kw">class</span> Exts, <span class="kw">class</span> LP, <span class="kw">class</span> CP<span class="op">&gt;</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mdarray<span class="op">&lt;</span>ET, Exts, LP, CP<span class="op">&gt;&amp;)</span>;</span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ET, <span class="kw">class</span> Exts, <span class="kw">class</span> LP, <span class="kw">class</span> CP<span class="op">&gt;</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="kw">const</span> mdarray<span class="op">&lt;</span>ET, Exts, LP, CP<span class="op">&gt;&amp;)</span>;</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>  <span class="co">// only in mdarray:</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ET, <span class="kw">class</span> Exts, <span class="kw">class</span> LP, <span class="kw">class</span> CP<span class="op">&gt;</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span>mdarray<span class="op">&lt;</span>ET, Exts, LP, CP<span class="op">&gt;&amp;&amp;)</span> <span class="kw">noexcept</span><span class="op">(</span><em>see-below</em><span class="op">)</span>;</span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ET, <span class="kw">class</span> Exts, <span class="kw">class</span> LP, <span class="kw">class</span> CP<span class="op">&gt;</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span>mdarray<span class="op">&lt;</span>ET, Exts, LP, CP<span class="op">&gt;&amp;&amp;)</span> <span class="kw">noexcept</span>;</span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>(The <code>noexcept</code> clauses on these constructors and
operators should probably actually derive from <code>noexcept</code>
clauses on the analogous functionality for the element type and policy
types).</p>
<p>Additionally, the analog of the
<code>mdspan(pointer, IndexType...)</code> constructor for
<code>mdarray</code> should not take the first argument, since the
<code>mdarray</code> owns the data and thus should be able to construct
it from sizes:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ElementType, <span class="kw">class</span> Extents, <span class="kw">class</span> LayoutPolicy, <span class="kw">class</span> ContainerPolicy<span class="op">&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> mdarray <span class="op">{</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// only in mdarray</span></span>
<span id="cb9-6"><a href="#cb9-6" 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> IndexType<span class="op">&gt;</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span>IndexType<span class="op">...)</span>;</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Note that in the completely static extents case, this is ambiguous
with the default constructor. For consistency in generic code, the
semantics of this constructor should be preferred over those of the
default constructor in that case.</p>
<p>By this same logic, we arrive at the <code>mapping_type</code>
constructor analogs:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ElementType, <span class="kw">class</span> Extents, <span class="kw">class</span> LayoutPolicy, <span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> mdarray <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// only in mdarray</span></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mapping_type<span class="op">&amp;)</span>;</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>There is some question as to whether we should also have constructors
that take <code>container_type</code> instances in addition to indices.
Consistency with standard container adapters like
<code>std::priority_queue</code> would dictate that we should. Note that
these constructors would copy data over.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ElementType, <span class="kw">class</span> Extents, <span class="kw">class</span> LayoutPolicy, <span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> mdarray <span class="op">{</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">// only in mdarray</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mapping_type<span class="op">&amp;)</span>;</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> container_type<span class="op">&amp;</span>, <span class="kw">const</span> mapping_type<span class="op">&amp;)</span>;</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Finally, we remmove the constructor that takes an
<code>array&lt;IndexType, N&gt;</code> of dynamic extents because of the
ambiguity or confusion with a constructor that takes a container
instance in the case where the <code>container</code> happens to be an
<code>array&lt;IndexType, N&gt;</code>.</p>
<h2 data-number="3.3" id="extents-design-reused"><span class="header-section-number">3.3</span> <code>Extents</code> Design
Reused<a href="#extents-design-reused" class="self-link"></a></h2>
<p>As with <code>mdspan</code>, the <code>Extents</code> template
parameter to <code>mdarray</code> shall be a template instantiation of
<code>std::extents</code>, as described in <span class="citation" data-cites="P0009R9">[<a href="#ref-P0009R9" role="doc-biblioref">P0009R9</a>]</span>. The concerns addressed by this
aspect of the design are exactly the same in <code>mdarray</code> and
<code>mdspan</code>, so using the same form and mechanism seems like the
right thing to do here.</p>
<h2 data-number="3.4" id="layoutpolicy-design-reused"><span class="header-section-number">3.4</span> <code>LayoutPolicy</code>
Design Reused<a href="#layoutpolicy-design-reused" class="self-link"></a></h2>
<p>While not quite as straightforward, the decision to use the same
design for <code>LayoutPolicy</code> from <code>mdspan</code> in
<code>mdarray</code> is still quite obviously the best choice. The only
piece that’s a bit of a less perfect fit is the
<code>is_contiguous()</code> and <code>is_always_contiguous()</code>
requirements. While non-contiguous use cases for <code>mdspan</code> are
quite common (e.g., <code>subspan()</code>), non-contiguous use cases
for <code>mdarray</code> are expected to be a bit more arcane.
Nonetheless, reasonable use cases do exist (for instance, padding of the
fast-running dimension in anticipation of a resize operation), and the
reduction in cognitive load due to concept reuse certainly justifies
reusing <code>LayoutPolicy</code> for <code>mdarray</code>.</p>
<h2 data-number="3.5" id="accessorpolicy-replaced-by-container"><span class="header-section-number">3.5</span> <code>AccessorPolicy</code>
Replaced by <code>Container</code><a href="#accessorpolicy-replaced-by-container" class="self-link"></a></h2>
<p>By far the most complicated aspect of the design for
<code>mdarray</code> is the analog of the <code>AccessorPolicy</code> in
<code>mdspan</code>. The <code>AccessorPolicy</code> for
<code>mdspan</code> is clearly designed with non-owning semantics in
mind–it provides a <code>pointer</code> type, a <code>reference</code>
type, and a means of converting from a pointer and an offset to a
reference. Beyond the lack of an allocation mechanism (that would be
needed by <code>mdarray</code>), the <code>AccessorPolicy</code>
requirements address concerns normally addressed by the allocation
mechanism itself. For instance, the C++ named requirements for
<code>Allocator</code> allow for the provision of the
<code>pointer</code> type to <code>std::vector</code> and other
containers. Arguably, consistency between <code>mdarray</code> and
standard library containers is far more important than with
<code>mdspan</code> in this respect. Several approaches to addressing
this incongruity are discussed below.</p>
<h3 data-number="3.5.1" id="expected-behavior-of-motivating-use-cases"><span class="header-section-number">3.5.1</span> Expected Behavior of
Motivating Use Cases<a href="#expected-behavior-of-motivating-use-cases" class="self-link"></a></h3>
<p>Regardless of the form of the solution, there are several use cases
where we have a clear understanding of how we want them to work. As
alluded to above, perhaps <em>the</em> most important motivating use
case for <code>mdarray</code> is that of small, fixed-size extents.
Consider a fictitious (not proposed) function,
<em>get-underlying-container</em>, that somehow retrieves the underlying
storage of an <code>mdarray</code>. For an <code>mdarray</code> of
entirely fixed sizes, we would expect the default implementation to
return something that is (at the very least) convertible to
<code>array</code> of the correct size:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> a <span class="op">=</span> mdarray<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">3</span>, <span class="dv">3</span><span class="op">&gt;()</span>;</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>array<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">9</span><span class="op">&gt;</span> data <span class="op">=</span> <em>get-underlying-container</em><span class="op">(</span>a<span class="op">)</span>; </span></code></pre></div>
<p>(Whether or not a reference to the underlying container should be
obtainable is slightly less clear, though we see no reason why this
should not be allowed.) The default for an <code>mdarray</code> with
variable extents is only slightly less clear, though it should almost
certainly meet the requirements of <em>contiguous container</em>
(<strong>[container.requirements.general]</strong>/13). The default
model for <em>contiguous container</em> of variable size in the standard
library is <code>vector</code>, so an entirely reasonable outcome would
be to have:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">auto</span> a <span class="op">=</span> mdarray<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">3</span>, dynamic_extent<span class="op">&gt;()</span>;</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>std<span class="op">::</span>vector<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> data <span class="op">=</span> <em>get-underlying-container</em><span class="op">(</span>a<span class="op">)</span>; </span></code></pre></div>
<p>Moreover, taking a view of a <code>mdarray</code> should yield an
analogous <code>mdspan</code> with consistent semantics (except, of
course, that the latter is non-owning). We provisionally call the method
for obtaining this analog <code>view()</code>:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T, <span class="kw">class</span> Extents, <span class="kw">class</span> LayoutPolicy, <span class="kw">class</span> ContainerPolicy<span class="op">&gt;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="dt">void</span> frobnicate<span class="op">(</span>mdarray<span class="op">&lt;</span>T, Extents, LayoutPolicy, ContainerPolicy<span class="op">&gt;</span> data<span class="op">)</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> data_view <span class="op">=</span> data<span class="op">.</span>view<span class="op">()</span>;</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>In order for this to work, <code>Container::data()</code> should be
required to return <code>T*</code>. That way interoperability with
<code>mdspan</code> is trivial, since it can simply be created as:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>template &lt;class T, class Extents, class LayoutPolicy, class ContainerPolicy&gt;</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>void frobnicate(mdarray&lt;T, Extents, LayoutPolicy, ContainerPolicy&gt; a)</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>{</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  mdspan a_view(a.data(), a.mapping());</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>  /* ... */</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<h3 data-number="3.5.2" id="analogs-in-the-standard-library-container-adapters"><span class="header-section-number">3.5.2</span> Analogs in the Standard
Library: Container Adapters<a href="#analogs-in-the-standard-library-container-adapters" class="self-link"></a></h3>
<p>Perhaps the best analogs for what <code>mdarray</code> is doing with
respect to allocation and ownership are the container adaptors
(<strong>[container.adaptors]</strong>), since they imbue additional
semantics to what is otherwise an ordinary container. These all take a
<code>Container</code> template parameter, which defaults to
<code>deque</code> for <code>stack</code> and <code>queue</code>, and to
<code>vector</code> for <code>priority_queue</code>. The allocation
concern is thus delegated to the container concept, reducing the
cognitive load associated with the design. While this design approach
overconstrains the template parameter slightly (i.e., not all of the
requirements of the <code>Container</code> concept are needed by the
container adaptors), the simplicity arising from concept reuse more than
justifies the cost of the extra constraints.</p>
<p>It is difficult to say whether the use of <code>Container</code>
directly, as with the container adaptors, is also the correct approach
for <code>mdarray</code>. There are pieces of information that may need
to be customized in some very reasonable use cases that are not provided
by the standard container concept. The most important of these is the
ability to produce a semantically consistent <code>AccessorPolicy</code>
when creating a <code>mdspan</code> that refers to a
<code>mdarray</code>. (Interoperability between <code>mdspan</code> and
<code>mdarray</code> is considered a critical design requirement because
of the nearly complete overlap in the set of algorithms that operate on
them.) For instance, given a <code>Container</code> instance
<code>c</code> and an <code>AccessorPolicy</code> instance
<code>a</code>, the behavior of <code>a.access(p, n)</code> should be
consistent with the behavior of <code>c[n]</code> for a
<code>mdspan</code> wrapping <code>a</code> that is a view of a
<code>mdarray</code> wrapping <code>c</code> (if <code>p</code> is
<code>c.begin()</code>). But because <code>c[n]</code> is part of the
container requirements and thus may encapsulate any arbitrary mapping
from an offset of <code>c.begin()</code> to a reference, the only
reasonable means of preserving these semantics for arbitrary container
types is to reference the original container directly in the
corresponding <code>AccessorPolicy</code>. In other words, the signature
for the <code>view()</code> method of <code>mdarray</code> would need to
look something like (ignoring, for the moment, whether the name for the
type of the accessor is specified or implementation-defined):</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> ElementType,</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> Extents,</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> LayoutPolicy,</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> mdarray <span class="op">{</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a> <span class="co">/* ... */</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a> mdspan<span class="op">&lt;</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>   ElementType, Extents, LayoutPolicy,</span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>   container_reference_accessor<span class="op">&lt;</span>Container<span class="op">&gt;&gt;</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a> view<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a> <span class="co">/* ... */</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> __container_reference_accessor <span class="op">{</span> <span class="co">// not proposed</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> pointer <span class="op">=</span> Container<span class="op">*</span>;</span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> Integer<span class="op">&gt;</span></span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a>  reference access<span class="op">(</span>pointer p, Integer offset<span class="op">)</span> <span class="op">{</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">(*</span>p<span class="op">)[</span>offset<span class="op">]</span>;</span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>But this approach comes at the cost of an additional indirection (one
for the pointer to the container, and one for the container dereference
itself), which is likely unacceptable cost in a facility designed to
target performance-sensitive use cases. The situation for the
<code>offset</code> requirement (which is used by <code>subspan</code>)
is potentially even worse for arbitrary non-contiguous containers,
adding up to one indirection per invocation of <code>subspan</code>.
This is likely unacceptable in many contexts.</p>
<p>Nonetheless, using refinements of the existing <code>Container</code>
concept directly with <code>mdarray</code> is an incredibly attractive
option because it avoids the introduction of an extra concept, and thus
significantly decreases the cognitive cost of the abstraction. Thus,
direct use of the existing <code>Container</code> concept hierarchy
should be preferred to other options unless the shortcomings of the
existing concept are so irreconcilable (or so complicated to reconcile)
as to create more cognitive load than is needed for an entirely new
concept.</p>
<p>One straight forward way to resolve the above concerns with arbitrary
container types, is to simply restrict what type of containers can be
used.</p>
<p>Specifically we would restrict it such that creating an
<code>mdspan</code> with <code>default_accessor</code> is straight
forward. Thus we would require:</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>std<span class="op">::</span>is_same_v<span class="op">&lt;</span><span class="kw">decltype</span><span class="op">(</span>Container<span class="op">::</span>data<span class="op">())</span>,ElementType<span class="op">*&gt;</span> <span class="op">==</span> <span class="kw">true</span></span></code></pre></div>
<p>and</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="op">&amp;</span>c<span class="op">[</span>i<span class="op">]</span> <span class="op">==</span> c<span class="op">.</span>data<span class="op">()+</span>i</span></code></pre></div>
<p>for all <code>i</code> in the range of <span class="math inline">[</span><code>0,c.size()</code><span class="math inline">)</span>.</p>
<p>In the following we discuss two design alternatives.</p>
<h3 data-number="3.5.3" id="not-proposed-alternative-a-dedicated-containerpolicy-concept"><span class="header-section-number">3.5.3</span> (Not Proposed) Alternative: A
Dedicated <code>ContainerPolicy</code> Concept<a href="#not-proposed-alternative-a-dedicated-containerpolicy-concept" class="self-link"></a></h3>
<p>Despite the additional cognitive load, there are a few arguments in
favor of using a dedicated concept for the container description of
<code>mdarray</code>. As is often the case with concept-driven design,
the implementation of <code>mdarray</code> only needs a relatively small
subset of the interface elements in the <code>Container</code> concept
hierarchy. This alone is not enough to justify an additional concept
external to the existing hierarchy; however, there are also quite a few
features missing from the existing container concept hierarchy, without
which an efficient <code>mdarray</code> implementation may be difficult
or impossible. As alluded to above, conversion to an
<code>AccessorPolicy</code> for the creation of a <code>mdspan</code> is
one missing piece. (Another, interestingly, is sized construction of the
container mixed with allocator awareness, which is surprisingly lacking
in the current hierarchy somehow.) For these reasons, it is worth
exploring a design based on analogy to the <code>AccessorPolicy</code>
concept rather than on analogy to <code>Container</code>. If we make
that abstraction owning, we might call it something like
<code>_ContainerLikeThing</code> (not proposed here; included for
discussion). In that case, a model of the
<code>_ContainerLikeThing</code> concept that meets the needs of
<code>mdarray</code> might look something like:</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">template</span> <span class="op">&lt;</span><span class="kw">class</span> ElementType, <span class="kw">class</span> Allocator<span class="op">=</span>std<span class="op">::</span>allocator<span class="op">&lt;</span>ElementType<span class="op">&gt;&gt;</span></span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> vector_container_like_thing <span class="co">// models _ContainerLikeThing</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> element_type <span class="op">=</span> ElementType;</span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> container_type <span class="op">=</span> std<span class="op">::</span>vector<span class="op">&lt;</span>ElementType, Allocator<span class="op">&gt;</span>;</span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> allocator_type <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>allocator_type;</span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> pointer <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>pointer;</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_pointer <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>const_pointer;</span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> reference <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>reference;</span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_reference <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>const_reference;</span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> accessor_policy <span class="op">=</span> std<span class="op">::</span>accessor_basic<span class="op">&lt;</span>element_type<span class="op">&gt;</span>;</span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_accessor_policy <span class="op">=</span> std<span class="op">::</span>accessor_basic<span class="op">&lt;</span><span class="kw">const</span> element_type<span class="op">&gt;</span>;</span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// analogous to `access` method in `AccessorPolicy`</span></span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a>  reference access<span class="op">(</span><span class="dt">ptrdiff_t</span> offset<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> __c<span class="op">[</span><span class="dt">size_t</span><span class="op">(</span>offset<span class="op">)]</span>; <span class="op">}</span></span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a>  const_reference access<span class="op">(</span><span class="dt">ptrdiff_t</span> offset<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> __c<span class="op">[</span><span class="dt">size_t</span><span class="op">(</span>offset<span class="op">)]</span>; <span class="op">}</span></span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Interface for mdspan creation</span></span>
<span id="cb19-20"><a href="#cb19-20" aria-hidden="true" tabindex="-1"></a>  accessor_policy make_accessor_policy<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{</span> <span class="op">}</span>; <span class="op">}</span></span>
<span id="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a>  const_accessor_policy make_accessor_policy<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> <span class="op">{</span> <span class="op">}</span>; <span class="op">}</span></span>
<span id="cb19-22"><a href="#cb19-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> pointer data<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span>  __c<span class="op">.</span>data<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb19-23"><a href="#cb19-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">typename</span> const_pointer data<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span>  __c<span class="op">.</span>data<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb19-24"><a href="#cb19-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-25"><a href="#cb19-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Interface for sized construction</span></span>
<span id="cb19-26"><a href="#cb19-26" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> vector_container_policy create<span class="op">(</span><span class="dt">size_t</span> n<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-27"><a href="#cb19-27" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> vector_container_like_thing<span class="op">{</span>container_type<span class="op">(</span>n, element_type<span class="op">{})}</span>;</span>
<span id="cb19-28"><a href="#cb19-28" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb19-29"><a href="#cb19-29" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> vector_container_policy create<span class="op">(</span><span class="dt">size_t</span> n, allocator_type <span class="kw">const</span><span class="op">&amp;</span> alloc<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-30"><a href="#cb19-30" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> vector_container_like_thing<span class="op">{</span>container_type<span class="op">(</span>n, element_type<span class="op">{}</span>, alloc<span class="op">)}</span>;</span>
<span id="cb19-31"><a href="#cb19-31" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb19-32"><a href="#cb19-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-33"><a href="#cb19-33" aria-hidden="true" tabindex="-1"></a>  container_type __c;</span>
<span id="cb19-34"><a href="#cb19-34" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>This approach solves many of the problems associated with using the
<code>Container</code> concept directly. It is the most flexible and
provides the best compatibility with <code>mdspan</code>, since the
conversion to analogous <code>AccessorPolicy</code> is fully
customizable. This comes at the cost of additional cognitive load, but
this can be justified based on the observation that almost half of the
functionality in the above sketch is absent from the container
hierarchy: the <code>make_accessor_policy()</code> requirement and the
sized, allocator-aware container creation
(<code>create(n, alloc)</code>) have no analogs in the container concept
hierarchy. Non-allocator-aware creation (<code>create(n)</code>) is
analogous to sized construction from the sequence container concept, the
<code>data()</code> method is analogous to <code>begin()</code> on the
contiguous container concept, and <code>access(n)</code> is analogous to
<code>operator[]</code> or <code>at(n)</code> from the optional sequence
container requirements. Even for these latter pieces of functionality,
though, we are required to combine several different concepts from the
<code>Container</code> hierarchy. Based on this analysis, we have
decided it is reasonable to pursue designs for this customization point
that diverge from <code>Container</code>, including ones that use
<code>AccessorPolicy</code> as a starting point. Given a better design,
we would definitely consider reversing direction on this decision, but
despite significant effort, we were unable to find a design that was
more than an awkward and forced fit for the <code>Container</code>
concept hierarchy.</p>
<h3 data-number="3.5.4" id="not-proposed-alternative-containerpolicy-subsumes-accessorpolicy"><span class="header-section-number">3.5.4</span> (Not Proposed) Alternative:
<code>ContainerPolicy</code> subsumes <code>AccessorPolicy</code><a href="#not-proposed-alternative-containerpolicy-subsumes-accessorpolicy" class="self-link"></a></h3>
<p>The above approach has the significant drawback that the
<code>_ContainerLikeThing</code> is an owning abstraction fairly similar
to a container that diverges from the <code>Container</code> hierarchy.
We initially explored this direction because it avoids having to provide
a <code>mdarray</code> constructor that takes both a
<code>Container</code> and a <code>ContainerPolicy</code>, which we felt
was a “design smell.” Another alternative along these lines is to make
the <code>mdarray</code> itself own the container instance and have the
<code>ContainerPolicy</code> (name subject to bikeshedding; maybe
<code>ContainerFactory</code> or <code>ContainerAccessor</code> is more
appropriate?) be a non-owning abstraction that describes the container
creation and access. While this approach leads to an ugly
<code>mdarray(container_type, mapping_type, ContainerPolicy)</code>
constructor, the analog that constructor affords to the
<code>mdspan(pointer, mapping_type, AccessorPolicy)</code> constructor
is a reasonable argument in favor of this design despite its quirkiness.
Furthermore, this approach affords the opportunity to explore a
<code>ContainerPolicy</code> design that subsumes
<code>AccessorPolicy</code>, thus providing the needed conversion to
<code>AccessorPolicy</code> for the analogous <code>mdspan</code> by
simple subsumption. More importantly, this subsumption would
significantly decrease the cognitive load for users already familiar
with <code>mdspan</code>. A model of <code>ContainerPolicy</code> for
this sort of approach might look something like:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> ElementType, <span class="kw">class</span> Allocator<span class="op">=</span>std<span class="op">::</span>allocator<span class="op">&lt;</span>ElementType<span class="op">&gt;&gt;</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> vector_container_policy <span class="co">// models ContainerPolicy (and thus AccessorPolicy)</span></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> element_type <span class="op">=</span> ElementType;</span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> container_type <span class="op">=</span> std<span class="op">::</span>vector<span class="op">&lt;</span>ElementType, Allocator<span class="op">&gt;</span>;</span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> allocator_type <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>allocator_type;</span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> pointer <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>pointer;</span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_pointer <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>const_pointer;</span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> reference <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>reference;</span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_reference <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>const_reference;</span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> offset_policy <span class="op">=</span> vector_container_policy<span class="op">&lt;</span>ElementType, Allocator<span class="op">&gt;</span></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-14"><a href="#cb20-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ContainerPolicy requirements:</span></span>
<span id="cb20-15"><a href="#cb20-15" aria-hidden="true" tabindex="-1"></a>  reference access<span class="op">(</span>container_type<span class="op">&amp;</span> c, <span class="dt">ptrdiff_t</span> i<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> c<span class="op">[</span><span class="dt">size_t</span><span class="op">(</span>i<span class="op">)]</span>; <span class="op">}</span></span>
<span id="cb20-16"><a href="#cb20-16" aria-hidden="true" tabindex="-1"></a>  const_reference access<span class="op">(</span>container_type <span class="kw">const</span><span class="op">&amp;</span> <span class="dt">ptrdiff_t</span> i<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> c<span class="op">[</span><span class="dt">size_t</span><span class="op">(</span>i<span class="op">)]</span>; <span class="op">}</span></span>
<span id="cb20-17"><a href="#cb20-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-18"><a href="#cb20-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ContainerPolicy requirements (interface for sized construction):</span></span>
<span id="cb20-19"><a href="#cb20-19" aria-hidden="true" tabindex="-1"></a>  container_type create<span class="op">(</span><span class="dt">size_t</span> n<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-20"><a href="#cb20-20" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> container_type<span class="op">(</span>n, element_type<span class="op">{})</span>;</span>
<span id="cb20-21"><a href="#cb20-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb20-22"><a href="#cb20-22" aria-hidden="true" tabindex="-1"></a>  container_type create<span class="op">(</span><span class="dt">size_t</span> n, allocator_type <span class="kw">const</span><span class="op">&amp;</span> alloc<span class="op">)</span> <span class="op">{</span></span>
<span id="cb20-23"><a href="#cb20-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> container_type<span class="op">(</span>n, element_type<span class="op">{}</span>, alloc<span class="op">)</span>;</span>
<span id="cb20-24"><a href="#cb20-24" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb20-25"><a href="#cb20-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-26"><a href="#cb20-26" aria-hidden="true" tabindex="-1"></a>  <span class="co">// AccessorPolicy requirement:</span></span>
<span id="cb20-27"><a href="#cb20-27" aria-hidden="true" tabindex="-1"></a>  reference access<span class="op">(</span>pointer p, <span class="dt">ptrdiff_t</span> i<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> p<span class="op">[</span>i<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb20-28"><a href="#cb20-28" aria-hidden="true" tabindex="-1"></a>  <span class="co">// For the const analog of AccessorPolicy:</span></span>
<span id="cb20-29"><a href="#cb20-29" aria-hidden="true" tabindex="-1"></a>  const_reference access<span class="op">(</span>const_pointer p, <span class="dt">ptrdiff_t</span> i<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> p<span class="op">[</span>i<span class="op">]</span>; <span class="op">}</span></span>
<span id="cb20-30"><a href="#cb20-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-31"><a href="#cb20-31" aria-hidden="true" tabindex="-1"></a>  <span class="co">// AccessorPolicy requirement:</span></span>
<span id="cb20-32"><a href="#cb20-32" aria-hidden="true" tabindex="-1"></a>  pointer offset<span class="op">(</span>pointer p, <span class="dt">ptrdiff_t</span> i<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> p <span class="op">+</span> i; <span class="op">}</span></span>
<span id="cb20-33"><a href="#cb20-33" aria-hidden="true" tabindex="-1"></a>  <span class="co">// For the const analog of AccessorPolicy:</span></span>
<span id="cb20-34"><a href="#cb20-34" aria-hidden="true" tabindex="-1"></a>  const_pointer offset<span class="op">(</span>const_pointer p, <span class="dt">ptrdiff_t</span> i<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> p <span class="op">+</span> i; <span class="op">}</span></span>
<span id="cb20-35"><a href="#cb20-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-36"><a href="#cb20-36" aria-hidden="true" tabindex="-1"></a>  <span class="co">// AccessorPolicy requirement:</span></span>
<span id="cb20-37"><a href="#cb20-37" aria-hidden="true" tabindex="-1"></a>  element_type<span class="op">*</span> decay<span class="op">(</span>pointer p<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> p; <span class="op">}</span></span>
<span id="cb20-38"><a href="#cb20-38" aria-hidden="true" tabindex="-1"></a>  <span class="co">// For the const analog of AccessorPolicy:</span></span>
<span id="cb20-39"><a href="#cb20-39" aria-hidden="true" tabindex="-1"></a>  <span class="kw">const</span> element_type<span class="op">*</span> decay<span class="op">(</span>pointer p<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> p; <span class="op">}</span></span>
<span id="cb20-40"><a href="#cb20-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-41"><a href="#cb20-41" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>The above sketch makes clear the biggest challenge with this
approach: the mismatch in shallow versus deep <code>const</code>ness in
for an abstractions designed to support <code>mdspan</code> and
<code>mdarray</code>, respectively. The <code>ContainerPolicy</code>
concept thus requires additional <code>const</code>-qualified overloads
of the basis operations. Moreover, while the
<code>ContainerPolicy</code> itself can be obtained directly from the
corresponding <code>AccessorPolicy</code> in the case of the
non-<code>const</code> method for creating the corresponding
<code>mdspan</code> (provisionally called <code>view()</code>), the
<code>const</code>-qualified version needs to adapt the policy, since
the nested types have the wrong names (e.g., <code>const_pointer</code>
should be named <code>pointer</code> from the perspective of the
<code>mdspan</code> that the <code>const</code>-qualified
<code>view()</code> needs to return). This could be fixed without too
much mess using an adapter (that does not need to be part of the
specification):</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>ContainerPolicy P<span class="op">&gt;</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> __const_accessor_policy_adapter <span class="op">{</span> <span class="co">// models AccessorPolicy</span></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> element_type <span class="op">=</span> add_const_t<span class="op">&lt;</span><span class="kw">typename</span> P<span class="op">::</span>element_type<span class="op">&gt;</span>;</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> pointer <span class="op">=</span> <span class="kw">typename</span> P<span class="op">::</span>const_pointer;</span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> reference <span class="op">=</span> <span class="kw">typename</span> P<span class="op">::</span>const_reference;</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> offset_policy <span class="op">=</span> __const_accessor_policy_adapter<span class="op">&lt;</span><span class="kw">typename</span> P<span class="op">::</span>offset_policy<span class="op">&gt;</span>;</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>  reference access<span class="op">(</span>pointer p, <span class="dt">ptrdiff_t</span> i<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> acc_<span class="op">.</span>access<span class="op">(</span>p, i<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>  pointer offset<span class="op">(</span>pointer p, <span class="dt">ptrdiff_t</span> i<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> acc_<span class="op">.</span>offset<span class="op">(</span>p, i<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>  element_type<span class="op">*</span> decay<span class="op">(</span>pointer p<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> acc_<span class="op">.</span>decay<span class="op">(</span>p<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>  <span class="op">[[</span><span class="at">no_unique_address</span><span class="op">]]</span> add_const_t<span class="op">&lt;</span>P<span class="op">&gt;</span> acc_;</span>
<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>Compared to simply using a <code>container</code> as the argument,
this approach has the benefit of enabling <code>mdarray</code> to use
containers for which <code>data()[i]</code> is not giving access to the
same element as <code>container[i]</code>. However, after more
consideration we believe that the need for supporting such containers as
underlying storage for <code>mdarray</code> is likely fairly niche.
Furthermore, we believe one could later extent the design of
<code>mdarray</code> to allow for such ContainerPolicies, even if the
initial design only allows for a restricted set of containers.</p>
<h1 data-number="4" id="wording"><span class="header-section-number">4</span> Wording<a href="#wording" class="self-link"></a></h1>
<p><b>22.7.� Class template <code>mdarray</code> [mdarray]</b></p>
<p><br /> <b>22.7.�.1 <code>mdarray</code> overview
[mdarray.overview]</b></p>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<code>mdarray</code> maps a multidimensional index in its domain to a
reference to an element in its codomain.</p>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
The <em>domain</em> of an <code>mdarray</code> object is a
multidimensional index space defined by an <code>extents</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
The <em>codomain</em> of an <code>mdarray</code> object is a set of
elements accessible from a contiguous range of integer indices.</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">namespace</span> std <span class="op">{</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ElementType, <span class="kw">class</span> Extents, <span class="kw">class</span> LayoutPolicy, <span class="kw">class</span> Container <span class="op">=</span> </span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>         <em>see below</em><span class="op">&gt;</span></span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> mdarray <span class="op">{</span></span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> extents_type <span class="op">=</span> Extents;</span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> layout_type <span class="op">=</span> LayoutPolicy;</span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> container_type <span class="op">=</span> Container;</span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> mapping_type <span class="op">=</span> <span class="kw">typename</span> layout_type<span class="op">::</span><span class="kw">template</span> mapping<span class="op">&lt;</span>extents_type<span class="op">&gt;</span>;</span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> element_type <span class="op">=</span> ElementType;</span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> value_type <span class="op">=</span> element_type;</span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> size_type <span class="op">=</span> <span class="kw">typename</span> Extents<span class="op">::</span>size_type ;</span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> pointer <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>pointer;</span>
<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> reference <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>reference;</span>
<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_pointer <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>const_pointer;</span>
<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_reference <span class="op">=</span> <span class="kw">typename</span> container_type<span class="op">::</span>const_reference;</span>
<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [mdspan.mdspan.ctors], mdspan Constructors</span></span>
<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">()</span> <span class="kw">requires</span><span class="op">(</span>rank_dynamic<span class="op">()</span> <span class="op">!=</span> <span class="dv">0</span><span class="op">)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mdarray<span class="op">&amp;</span> rhs<span class="op">)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span>mdarray<span class="op">&amp;&amp;</span> rhs<span class="op">)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-24"><a href="#cb22-24" 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> SizeTypes<span class="op">&gt;</span></span>
<span id="cb22-25"><a href="#cb22-25" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>rank<span class="op">()&gt;</span><span class="dv">0</span> <span class="op">||</span> rank_dynamic<span class="op">()==</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb22-26"><a href="#cb22-26" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span>SizeTypes<span class="op">...</span> exts<span class="op">)</span>;</span>
<span id="cb22-27"><a href="#cb22-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> Extents<span class="op">&amp;</span> ext<span class="op">)</span>;</span>
<span id="cb22-28"><a href="#cb22-28" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mapping_type<span class="op">&amp;</span> m<span class="op">)</span>;</span>
<span id="cb22-29"><a href="#cb22-29" aria-hidden="true" tabindex="-1"></a>  </span>
<span id="cb22-30"><a href="#cb22-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-31"><a href="#cb22-31" 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> SizeTypes<span class="op">&gt;</span></span>
<span id="cb22-32"><a href="#cb22-32" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> container_type<span class="op">&amp;</span> c, SizeTypes<span class="op">...</span> exts<span class="op">)</span>;</span>
<span id="cb22-33"><a href="#cb22-33" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> container_type<span class="op">&amp;</span> c, <span class="kw">const</span> extents_type<span class="op">&amp;</span> ext<span class="op">)</span>;</span>
<span id="cb22-34"><a href="#cb22-34" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> container_type<span class="op">&amp;</span> c, <span class="kw">const</span> mapping_type<span class="op">&amp;</span> m<span class="op">)</span>;</span>
<span id="cb22-35"><a href="#cb22-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-36"><a href="#cb22-36" 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> SizeTypes<span class="op">&gt;</span></span>
<span id="cb22-37"><a href="#cb22-37" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span>container_type<span class="op">&amp;&amp;</span> c, SizeTypes<span class="op">...</span> exts<span class="op">)</span>;</span>
<span id="cb22-38"><a href="#cb22-38" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span>container_type<span class="op">&amp;&amp;</span> c, <span class="kw">const</span> extents_type<span class="op">&amp;</span> ext<span class="op">)</span>;</span>
<span id="cb22-39"><a href="#cb22-39" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span>container_type<span class="op">&amp;&amp;</span> c, <span class="kw">const</span> mapping_type<span class="op">&amp;</span> m<span class="op">)</span>;</span>
<span id="cb22-40"><a href="#cb22-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-41"><a href="#cb22-41" 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> SizeTypes<span class="op">&gt;</span></span>
<span id="cb22-42"><a href="#cb22-42" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span>initializer_list<span class="op">&lt;</span>T<span class="op">&gt;</span> init, SizeTypes<span class="op">...</span> exts<span class="op">)</span>;</span>
<span id="cb22-43"><a href="#cb22-43" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span>initializer_list<span class="op">&lt;</span>T<span class="op">&gt;</span> init, <span class="kw">const</span> extents_type<span class="op">&amp;</span> ext<span class="op">)</span>;</span>
<span id="cb22-44"><a href="#cb22-44" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span>initializer_list<span class="op">&lt;</span>T<span class="op">&gt;</span> init, <span class="kw">const</span> mapping_type<span class="op">&amp;</span> m<span class="op">)</span>;</span>
<span id="cb22-45"><a href="#cb22-45" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-46"><a href="#cb22-46" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherElementType, <span class="kw">class</span> OtherExtents, </span>
<span id="cb22-47"><a href="#cb22-47" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> OtherLayoutPolicy, <span class="kw">class</span> OtherContainer<span class="op">&gt;</span></span>
<span id="cb22-48"><a href="#cb22-48" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span><span class="op">(</span><em>see below</em><span class="op">)</span></span>
<span id="cb22-49"><a href="#cb22-49" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span></span>
<span id="cb22-50"><a href="#cb22-50" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> mdarray<span class="op">&lt;</span>OtherElementType, OtherExtents, </span>
<span id="cb22-51"><a href="#cb22-51" aria-hidden="true" tabindex="-1"></a>                   OtherLayoutPolicy, OtherContainer<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span>
<span id="cb22-52"><a href="#cb22-52" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-53"><a href="#cb22-53" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc, <span class="kw">class</span><span class="op">...</span> SizeTypes<span class="op">&gt;</span></span>
<span id="cb22-54"><a href="#cb22-54" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb22-55"><a href="#cb22-55" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> Extents<span class="op">&amp;</span> ext, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span>
<span id="cb22-56"><a href="#cb22-56" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb22-57"><a href="#cb22-57" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb22-58"><a href="#cb22-58" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mapping_type<span class="op">&amp;</span> m, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span>
<span id="cb22-59"><a href="#cb22-59" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-60"><a href="#cb22-60" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb22-61"><a href="#cb22-61" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb22-62"><a href="#cb22-62" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> container_type<span class="op">&amp;</span> c, <span class="kw">const</span> extents_type<span class="op">&amp;</span> ext<span class="op">)</span>;</span>
<span id="cb22-63"><a href="#cb22-63" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb22-64"><a href="#cb22-64" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb22-65"><a href="#cb22-65" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> container_type<span class="op">&amp;</span> c, <span class="kw">const</span> mapping_type<span class="op">&amp;</span> m<span class="op">)</span>;</span>
<span id="cb22-66"><a href="#cb22-66" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-67"><a href="#cb22-67" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb22-68"><a href="#cb22-68" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb22-69"><a href="#cb22-69" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span>container_type<span class="op">&amp;&amp;</span> c, <span class="kw">const</span> extents_type<span class="op">&amp;</span> ext<span class="op">)</span>;</span>
<span id="cb22-70"><a href="#cb22-70" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb22-71"><a href="#cb22-71" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb22-72"><a href="#cb22-72" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span>container_type<span class="op">&amp;&amp;</span> c, <span class="kw">const</span> mapping_type<span class="op">&amp;</span> m<span class="op">)</span>;</span>
<span id="cb22-73"><a href="#cb22-73" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-74"><a href="#cb22-74" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb22-75"><a href="#cb22-75" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb22-76"><a href="#cb22-76" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span>initializer_list<span class="op">&lt;</span>T<span class="op">&gt;</span> init, <span class="kw">const</span> extents_type<span class="op">&amp;</span> ext<span class="op">)</span>;</span>
<span id="cb22-77"><a href="#cb22-77" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb22-78"><a href="#cb22-78" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb22-79"><a href="#cb22-79" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span>initializer_list<span class="op">&lt;</span>T<span class="op">&gt;</span> init, <span class="kw">const</span> mapping_type<span class="op">&amp;</span> m<span class="op">)</span>;</span>
<span id="cb22-80"><a href="#cb22-80" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-81"><a href="#cb22-81" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherElementType, <span class="kw">class</span> OtherExtents, </span>
<span id="cb22-82"><a href="#cb22-82" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> OtherLayoutPolicy, <span class="kw">class</span> OtherContainer, </span>
<span id="cb22-83"><a href="#cb22-83" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb22-84"><a href="#cb22-84" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span><span class="op">(</span><em>see below</em><span class="op">)</span></span>
<span id="cb22-85"><a href="#cb22-85" aria-hidden="true" tabindex="-1"></a>    <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb22-86"><a href="#cb22-86" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span></span>
<span id="cb22-87"><a href="#cb22-87" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> mdarray<span class="op">&lt;</span>OtherElementType, OtherExtents, </span>
<span id="cb22-88"><a href="#cb22-88" aria-hidden="true" tabindex="-1"></a>                   OtherLayoutPolicy, OtherContainer<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span>
<span id="cb22-89"><a href="#cb22-89" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-90"><a href="#cb22-90" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span><span class="kw">const</span> mdarray<span class="op">&amp;</span> rhs<span class="op">)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb22-91"><a href="#cb22-91" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span>mdarray<span class="op">&amp;&amp;</span> rhs<span class="op">)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb22-92"><a href="#cb22-92" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-93"><a href="#cb22-93" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [mdspan.mdspan.members], mdspan members</span></span>
<span id="cb22-94"><a href="#cb22-94" 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> SizeTypes<span class="op">&gt;</span></span>
<span id="cb22-95"><a href="#cb22-95" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> reference <span class="kw">operator</span><span class="op">[](</span>SizeTypes<span class="op">...</span> indices<span class="op">)</span>;</span>
<span id="cb22-96"><a href="#cb22-96" 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> SizeTypes<span class="op">&gt;</span></span>
<span id="cb22-97"><a href="#cb22-97" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> const_reference <span class="kw">operator</span><span class="op">[](</span>SizeTypes<span class="op">...</span> indices<span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb22-98"><a href="#cb22-98" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> SizeType, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb22-99"><a href="#cb22-99" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> reference <span class="kw">operator</span><span class="op">[](</span><span class="kw">const</span> array<span class="op">&lt;</span>SizeType, N<span class="op">&gt;&amp;</span> indices<span class="op">)</span>;</span>
<span id="cb22-100"><a href="#cb22-100" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> SizeType, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb22-101"><a href="#cb22-101" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> const_reference <span class="kw">operator</span><span class="op">[](</span><span class="kw">const</span> array<span class="op">&lt;</span>SizeType, N<span class="op">&gt;&amp;</span> indices<span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb22-102"><a href="#cb22-102" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-103"><a href="#cb22-103" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">size_t</span> rank<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> Extents<span class="op">::</span>rank<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb22-104"><a href="#cb22-104" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">size_t</span> rank_dynamic<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> Extents<span class="op">::</span>rank_dynamic<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb22-105"><a href="#cb22-105" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> size_type static_extent<span class="op">(</span><span class="dt">size_t</span> r<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> Extents<span class="op">::</span>static_extent<span class="op">(</span>r<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb22-106"><a href="#cb22-106" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-107"><a href="#cb22-107" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">const</span> extents_type<span class="op">&amp;</span> extents<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> <em>map_</em><span class="op">.</span>extents<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb22-108"><a href="#cb22-108" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> size_type extent<span class="op">(</span><span class="dt">size_t</span> r<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> extents<span class="op">().</span>extent<span class="op">(</span>r<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb22-109"><a href="#cb22-109" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> size_type size<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb22-110"><a href="#cb22-110" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-111"><a href="#cb22-111" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> pointer data<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> ctr\_<span class="op">.</span>data<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb22-112"><a href="#cb22-112" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> const_pointer data<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> ctr\_<span class="op">.</span>data<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb22-113"><a href="#cb22-113" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> container_type<span class="op">&amp;</span> container<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> ctr\_; <span class="op">}</span></span>
<span id="cb22-114"><a href="#cb22-114" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">const</span> container_type<span class="op">&amp;</span> container<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> ctr\_; <span class="op">}</span></span>
<span id="cb22-115"><a href="#cb22-115" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">const</span> mapping_type<span class="op">&amp;</span> mapping<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> <em>map_</em>; <span class="op">}</span></span>
<span id="cb22-116"><a href="#cb22-116" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-117"><a href="#cb22-117" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherElementType, <span class="kw">class</span> OtherExtents,</span>
<span id="cb22-118"><a href="#cb22-118" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> OtherLayoutType, <span class="kw">class</span> OtherAccessorType<span class="op">&gt;</span></span>
<span id="cb22-119"><a href="#cb22-119" aria-hidden="true" tabindex="-1"></a>  <span class="kw">operator</span> mdspan <span class="op">()</span>;</span>
<span id="cb22-120"><a href="#cb22-120" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-121"><a href="#cb22-121" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-122"><a href="#cb22-122" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span> is_always_unique<span class="op">()</span> <span class="op">{</span></span>
<span id="cb22-123"><a href="#cb22-123" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> mapping_type<span class="op">::</span>is_always_unique<span class="op">()</span>;</span>
<span id="cb22-124"><a href="#cb22-124" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb22-125"><a href="#cb22-125" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span> is_always_contiguous<span class="op">()</span> <span class="op">{</span></span>
<span id="cb22-126"><a href="#cb22-126" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> mapping_type<span class="op">::</span>is_always_contiguous<span class="op">()</span>;</span>
<span id="cb22-127"><a href="#cb22-127" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb22-128"><a href="#cb22-128" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span> is_always_strided<span class="op">()</span> <span class="op">{</span></span>
<span id="cb22-129"><a href="#cb22-129" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> mapping_type<span class="op">::</span>is_always_strided<span class="op">()</span>;</span>
<span id="cb22-130"><a href="#cb22-130" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb22-131"><a href="#cb22-131" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-132"><a href="#cb22-132" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_unique<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb22-133"><a href="#cb22-133" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <em>map_</em><span class="op">.</span>is_unique<span class="op">()</span>;</span>
<span id="cb22-134"><a href="#cb22-134" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb22-135"><a href="#cb22-135" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_contiguous<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb22-136"><a href="#cb22-136" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <em>map_</em><span class="op">.</span>is_contiguous<span class="op">()</span>;</span>
<span id="cb22-137"><a href="#cb22-137" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb22-138"><a href="#cb22-138" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_strided<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb22-139"><a href="#cb22-139" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <em>map_</em><span class="op">.</span>is_strided<span class="op">()</span>;</span>
<span id="cb22-140"><a href="#cb22-140" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb22-141"><a href="#cb22-141" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> size_type stride<span class="op">(</span><span class="dt">size_t</span> r<span class="op">)</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb22-142"><a href="#cb22-142" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <em>map_</em><span class="op">.</span>stride<span class="op">(</span>r<span class="op">)</span>;</span>
<span id="cb22-143"><a href="#cb22-143" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb22-144"><a href="#cb22-144" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-145"><a href="#cb22-145" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb22-146"><a href="#cb22-146" aria-hidden="true" tabindex="-1"></a>  container_type ctr_;</span>
<span id="cb22-147"><a href="#cb22-147" aria-hidden="true" tabindex="-1"></a>  mapping_type <em>map_</em>; <span class="co">// <em>exposition only</em></span></span>
<span id="cb22-148"><a href="#cb22-148" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<code>mdarray&lt;ElementType, Extents, LayoutPolicy, Accessor&gt;</code>
is a trivially copyable type if <code>Container</code> and
<code>LayoutPolicy::mapping_type&lt;Extents&gt;</code> are trivially
copyable types.</p>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
<code>ElementType</code> is required to be a complete object type that
is neither an abstract class type nor an array type. If
<code>Extents</code> is not a specialization of <code>extents</code>,
then the program is ill-formed. <code>LayoutPolicy</code> shall meet the
layout mapping policy requirements. <code>Container</code> shall meet
the requirements of ContiguousContainer. If
<code>is_same_v&lt;typename Container::value_type, ElementType&gt;</code>
equals <code>false</code>, then the program is ill-formed.</p>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
The default type for <code>Container</code> is
<code>vector&lt;ElementType&gt;</code> if
<code>Extents::dynamic_rank()&gt;0</code> is <code>true</code>.
Otherwise, the default type is <code>array&lt;ElementType,N&gt;</code>,
where <code>N</code> is the product of
<code>Extents::static_extent(r)</code> for <code>r</code> in the range
of <span class="math inline">[</span><code>0, Extents::rank()</code><span class="math inline">)</span>.</p>
<!--

 ##              #               #
#   ### ##   ## ### ### # # ### ### ### ###  ##
#   # # # #  #   #  #   # # #    #  # # #    #
#   ### # # ##   ## #   ### ###  ## ### #   ##
 ##

-->
<p><b>22.7.�.1 <code>mdarray</code> Constructors [mdarray.ctors]</b></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">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> SizeTypes<span class="op">&gt;</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">(</span>rank<span class="op">()&gt;</span><span class="dv">0</span> <span class="op">||</span> rank_dynamic<span class="op">()==</span><span class="dv">0</span><span class="op">)</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span>SizeTypes<span class="op">...</span> exts<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.1)</a></span>
<code>(is_convertible_v&lt;SizeTypes, size_type&gt; &amp;&amp; ...)</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.2)</a></span>
<code>is_constructible_v&lt;Extents, static_cast&lt;size_type&gt;(SizeTypes)...&gt;</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.3)</a></span>
<code>is_constructible_v&lt;mapping_type, Extents&gt;</code> is
<code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.4)</a></span>
<code>is_constructible_v&lt;container_type, size_t&gt;</code> is
<code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>Extents(static_cast&lt;size_type&gt;(std::move(exts))...)</code>,
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>container_type(</code><em><code>map_</code></em><code>.required_span_size())</code>.</p></li>
</ul>
<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">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> extents_type<span class="op">&amp;</span> ext<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.1)</a></span>
<code>is_constructible_v&lt;mapping_type, const extents_type&amp;&gt;</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.2)</a></span>
<code>is_constructible_v&lt;container_type, size_t&gt;</code> is
<code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(4.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>ext</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(4.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>container_type(</code><em><code>map_</code></em><code>.required_span_size())</code>.</p></li>
</ul>
<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">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mapping_type<span class="op">&amp;</span> m<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
<em>Constraints:</em>
<code>is_constructible_v&lt;container_type, size_t&gt;</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>m</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>container_type(</code><em><code>map_</code></em><code>.required_span_size())</code>.</p></li>
</ul>
<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">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> SizeTypes<span class="op">&gt;</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> container_type<span class="op">&amp;</span> c, SizeTypes<span class="op">...</span> exts<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(7.1)</a></span>
<code>(is_convertible_v&lt;SizeTypes, size_type&gt; &amp;&amp; ...)</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(7.2)</a></span>
<code>is_constructible_v&lt;extents_type, static_cast&lt;size_type&gt;(SizeTypes)...&gt;</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(7.3)</a></span>
<code>is_constructible_v&lt;mapping_type, extents_type&gt;</code> is
<code>true</code>, and</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
<em>Preconditions:</em>
<code>c.size() == mapping_type(extents_type(static_cast&lt;size_type&gt;(std::move(exts))...)).required_span_size()</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(9.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>extents_type(static_cast&lt;size_type&gt;(std::move(exts))...)</code>,
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(9.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>c</code>.</p></li>
</ul>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> container_type<span class="op">&amp;</span> c, <span class="kw">const</span> extents_type<span class="op">&amp;</span> ext<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">10</a></span>
<em>Constraints:</em>
<code>is_constructible_v&lt;mapping_type, const extents_type&amp;&gt;</code>
is <code>true</code>, and</p>
<p><span class="marginalizedparent"><a class="marginalized">11</a></span>
<em>Preconditions:</em>
<code>c.size() == mapping_type(ext).required_span_size()</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">12</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(12.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>ext</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(12.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>c</code>.</p></li>
</ul>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> container_type<span class="op">&amp;</span> c, <span class="kw">const</span> mapping_type<span class="op">&amp;</span> m<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">13</a></span>
<em>Preconditions:</em> <code>c.size() == m.required_span_size()</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">14</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(14.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>m</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(14.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>c</code>.</p></li>
</ul>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> SizeTypes<span class="op">&gt;</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span>container_type<span class="op">&amp;&amp;</span> c, SizeTypes<span class="op">...</span> exts<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">15</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(15.1)</a></span>
<code>(is_convertible_v&lt;SizeTypes, size_type&gt; &amp;&amp; ...)</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(15.2)</a></span>
<code>is_constructible_v&lt;extents_type, static_cast&lt;size_type&gt;(SizeTypes)...&gt;</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(15.3)</a></span>
<code>is_constructible_v&lt;mapping_type, extents_type&gt;</code> is
<code>true</code>, and</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">16</a></span>
<em>Preconditions:</em>
<code>c.size() == mapping_type(extents_type(static_cast&lt;size_type&gt;(std::move(exts))...)).required_span_size()</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">17</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(17.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>extents_type(static_cast&lt;size_type&gt;(std::move(exts))...)</code>,
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(17.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>std::move(c)</code>.</p></li>
</ul>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> mdarray<span class="op">(</span>container_type<span class="op">&amp;&amp;</span> c, <span class="kw">const</span> extents_type<span class="op">&amp;</span> ext<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">18</a></span>
<em>Constraints:</em>
<code>is_constructible_v&lt;mapping_type, const extents_type&amp;&gt;</code>
is <code>true</code>, and</p>
<p><span class="marginalizedparent"><a class="marginalized">18</a></span>
<em>Preconditions:</em>
<code>c.size() == mapping_type(ext).required_span_size()</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">19</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(19.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>ext</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(19.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>std::move(c)</code>.</p></li>
</ul>
<div class="sourceCode" id="cb31"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> mdarray<span class="op">(</span>container_type<span class="op">&amp;&amp;</span> c, <span class="kw">const</span> mapping_type<span class="op">&amp;</span> m<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">20</a></span>
<em>Preconditions:</em> <code>c.size() == m.required_span_size()</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">21</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(21.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>m</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(22.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>std::move(c)</code>.</p></li>
</ul>
<div class="sourceCode" id="cb32"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherElementType, <span class="kw">class</span> OtherExtents,</span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> OtherLayoutPolicy, <span class="kw">class</span> OtherContainer<span class="op">&gt;</span></span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span><span class="op">(</span><em>see below</em><span class="op">)</span></span>
<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mdarray<span class="op">&lt;</span>OtherElementType, OtherExtents, </span>
<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>                                OtherLayoutPolicy, OtherContainer<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">23</a></span>
<em>Mandates:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(23.1)</a></span>
<code>is_constructible_v&lt;Container, const OtherContainer&amp;&gt;</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(23.2)</a></span>
<code>is_constructible_v&lt;extents_type, OtherExtents&gt;</code> is
<code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">24</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(24.1)</a></span>
<code>is_constructible_v&lt;mapping_type, const OtherLayoutPolicy::template mapping&lt;OtherExtents&gt;&amp;&gt;</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(24.2)</a></span>
<code>is_constructible_v&lt;container_type, OtherContainer&gt;</code> is
<code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">25</a></span>
<em>Preconditions:</em></p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(25.1)</a></span> For
each rank index <code>r</code> of <code>extents_type</code>,
<code>static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r)</code>
is <code>true</code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">26</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(26.1)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>other.ctr_</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(26.2)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>other.</code><em><code>map_</code></em>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">27</a></span>
<em>Remarks:</em> The expression inside <code>explicit</code> is:</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a>  <span class="op">!</span>is_convertible_v<span class="op">&lt;</span><span class="kw">const</span> <span class="kw">typename</span> OtherLayoutPolicy<span class="op">::</span>mapping_type<span class="op">&amp;</span>, mapping_type<span class="op">&gt;</span> <span class="op">||</span></span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">!</span>is_convertible_v<span class="op">&lt;</span><span class="kw">const</span> OtherContainer<span class="op">&amp;</span>, Container<span class="op">&gt;</span></span></code></pre></div>
<div class="sourceCode" id="cb34"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> extents_type<span class="op">&amp;</span> ext, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">28</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(28.1)</a></span>
<code>is_constructible_v&lt;mapping_type, const extents_type&amp;&gt;</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(28.2)</a></span>
<code>is_constructible_v&lt;container_type, size_t, Alloc&gt;</code> is
<code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">29</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(29.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>ext</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(29.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<em><code>map_</code></em><code>.required_span_size()</code> as the
first argument and <code>a</code> as the second argument.</p></li>
</ul>
<div class="sourceCode" id="cb35"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mapping_type<span class="op">&amp;</span> m, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">30</a></span>
<em>Constraints:</em>
<code>is_constructible_v&lt;container_type, size_t, Alloc&gt;</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">31</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(31.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>m</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(31.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>m.required_span_size()</code> as the first argument and
<code>a</code> as the second argument.</p></li>
</ul>
<div class="sourceCode" id="cb36"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> container_type<span class="op">&amp;</span> c, <span class="kw">const</span> extents_type<span class="op">&amp;</span> ext, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">32</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(32.1)</a></span>
<code>is_constructible_v&lt;mapping_type, const extents_type&amp;&gt;</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(32.2)</a></span>
<code>is_constructible_v&lt;container_type, container_type, Alloc&gt;</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">33</a></span>
<em>Preconditions:</em>
<code>c.size() == mapping_type(ext).required_span_size()</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">34</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(34.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>ext</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(34.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with <code>c</code> as the
first argument and <code>a</code> as the second argument.</p></li>
</ul>
<div class="sourceCode" id="cb37"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> container_type<span class="op">&amp;</span> c, <span class="kw">const</span> mapping_type<span class="op">&amp;</span> m, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">35</a></span>
<em>Constraints:</em>
<code>is_constructible_v&lt;container_type, container_type, Alloc&gt;</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">36</a></span>
<em>Preconditions:</em> <code>c.size() == m.required_span_size()</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">37</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(37.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>m</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(37.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with <code>c</code> as the
first argument and <code>a</code> as the second argument.</p></li>
</ul>
<div class="sourceCode" id="cb38"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span>container_type<span class="op">&amp;&amp;</span> c, <span class="kw">const</span> extents_type<span class="op">&amp;</span> ext, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">38</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(38.1)</a></span>
<code>is_constructible_v&lt;mapping_type, const extents_type&amp;&gt;</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(38.2)</a></span>
<code>is_constructible_v&lt;container_type, container_type, Alloc&gt;</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">39</a></span>
<em>Preconditions:</em>
<code>c.size() == mapping_type(ext).required_span_size()</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">40</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(40.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>ext</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(40.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>std::move(c)</code> as the first argument and <code>a</code> as
the second argument.</p></li>
</ul>
<div class="sourceCode" id="cb39"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">requires</span><span class="op">(</span>uses_allocator_v<span class="op">&lt;</span>container_type, Alloc<span class="op">&gt;)</span></span>
<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span>container_type<span class="op">&amp;&amp;</span> c, <span class="kw">const</span> mapping_type<span class="op">&amp;</span> m, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">41</a></span>
<em>Constraints:</em>
<code>is_constructible_v&lt;container_type, container_type, Alloc&gt;</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">42</a></span>
<em>Preconditions:</em> <code>c.size() == m.required_span_size()</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">43</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(43.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>m</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(43.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>std::move(c)</code> as the first argumnet and <code>a</code> as
the second argument.</p></li>
</ul>
<div class="sourceCode" id="cb40"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherElementType, <span class="kw">class</span> OtherExtents,</span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> OtherLayoutPolicy, <span class="kw">class</span> OtherContainer, <span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span><span class="op">(</span><em>see below</em><span class="op">)</span></span>
<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mdarray<span class="op">&lt;</span>OtherElementType, OtherExtents, </span>
<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a>                                  OtherLayoutPolicy, OtherContainer<span class="op">&gt;&amp;</span> other,</span>
<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a>                    <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">44</a></span>
<em>Mandates:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(44.1)</a></span>
<code>is_constructible_v&lt;Container, OtherContainer, Alloc&gt;</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(44.2)</a></span>
<code>is_constructible_v&lt;extents_type, OtherExtents&gt;</code> is
<code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">45</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(45.1)</a></span>
<code>is_constructible_v&lt;mapping_type, const OtherLayoutPolicy::template mapping&lt;OtherExtents&gt;&amp;&gt;</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(45.2)</a></span>
<code>is_constructible_v&lt;container_type, OtherContainer, Alloc&gt;</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">46</a></span>
<em>Preconditions:</em></p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(46.1)</a></span> For
each rank index <code>r</code> of <code>extents_type</code>,
<code>static_extent(r) == dynamic_extent || static_extent(r) == other.extent(r)</code>
is <code>true</code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">47</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(47.2)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>other.</code><em><code>map_</code></em>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(47.1)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>other.ctr_</code> as the first argument and <code>a</code> as the
second argument.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">48</a></span>
<em>Remarks:</em> The expression inside <code>explicit</code> is:</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>  <span class="op">!</span>is_convertible_v<span class="op">&lt;</span><span class="kw">const</span> <span class="kw">typename</span> OtherLayoutPolicy<span class="op">::</span>mapping_type<span class="op">&amp;</span>, mapping_type<span class="op">&gt;</span> <span class="op">||</span></span>
<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">!</span>is_convertible_v<span class="op">&lt;</span><span class="kw">const</span> OtherContainer<span class="op">&amp;</span>, Container<span class="op">&gt;</span></span></code></pre></div>
<!--

  #              #                           #
### ### ###  ##     ##      ###  ## ### ###     ##  ###
# # # # ### # #  #  # #     ### # # # # # #  #  # # # #
### ### # # ###  ## # #     # # ### ### ###  ## # #  ##
                                    #   #           ###
-->
<p><br /> <b>22.7.�.2 <code>mdarray</code> members
[mdarray.members]</b></p>
<div class="sourceCode" id="cb42"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb42-1"><a href="#cb42-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> SizeTypes<span class="op">&gt;</span></span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> reference <span class="kw">operator</span><span class="op">[](</span>SizeTypes<span class="op">...</span> indices<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.1)</a></span>
<code>(is_convertible_v&lt;SizeTypes, size_type&gt; &amp;&amp; ...)</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.2)</a></span>
<code>(is_nothrow_constructible_v&lt;size_type, SizeTypes&gt; &amp;&amp; ...)</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.3)</a></span>
<code>sizeof...(SizeTypes) == rank()</code> is
<code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
Let <code>I</code> be
<code>static_cast&lt;size_type&gt;(std::move(indices))</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>Preconditions:</em> <code>I</code> is a multidimensional index into
<code>extents()</code>. <i>[Note:</i> This implies that
<em><code>map_</code></em><code>(I...) &lt;</code><em><code>map_</code></em><code>.required_span_size()</code>
is <code>true</code>.<i>— end note]</i>;</p>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<em>Effects:</em> Equivalent to:
<code>return ctr_[</code><em><code>map_</code></em><code>(I...)];</code>.</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb43-1"><a href="#cb43-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> SizeTypes<span class="op">&gt;</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> const_reference <span class="kw">operator</span><span class="op">[](</span>SizeTypes<span class="op">...</span> indices<span class="op">)</span> <span class="kw">const</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.1)</a></span>
<code>(is_convertible_v&lt;SizeTypes, size_type&gt; &amp;&amp; ...)</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.2)</a></span>
<code>(is_nothrow_constructible_v&lt;size_type, SizeTypes&gt; &amp;&amp; ...)</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.3)</a></span>
<code>sizeof...(SizeTypes) == rank()</code> is
<code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
Let <code>I</code> be
<code>static_cast&lt;size_type&gt;(std::move(indices))</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<em>Preconditions:</em> <code>I</code> is a multidimensional index into
<code>extents()</code>. <i>[Note:</i> This implies that
<em><code>map_</code></em><code>(I...) &lt;</code><em><code>map_</code></em><code>.required_span_size()</code>
is <code>true</code>.<i>— end note]</i>;</p>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
<em>Effects:</em> Equivalent to:
<code>return ctr_[</code><em><code>map_</code></em><code>(I...)];</code>.</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> SizeType, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> reference <span class="kw">operator</span><span class="op">[](</span><span class="kw">const</span> array<span class="op">&lt;</span>SizeType, N<span class="op">&gt;&amp;</span> indices<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(9.1)</a></span>
<code>is_convertible_v&lt;const SizeType&amp;, size_type&gt;</code> is
<code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(9.2)</a></span>
<code>is_nothrow_constructible_v&lt;size_type, const SizeType&amp;&gt;</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(9.3)</a></span>
<code>rank() == N</code> is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">10</a></span>
<em>Effects:</em> Let <code>P</code> be the parameter pack such that
<code>is_same_v&lt;make_index_sequence&lt;rank()&gt;, index_sequence&lt;P...&gt;&gt;</code>
is <code>true</code>. <br /> Equivalent to:
<code>return operator[](static_cast&lt;size_type&gt;(indices[P])...);</code></p>
<div class="sourceCode" id="cb45"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> SizeType, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> const_reference <span class="kw">operator</span><span class="op">[](</span><span class="kw">const</span> array<span class="op">&lt;</span>SizeType, N<span class="op">&gt;&amp;</span> indices<span class="op">)</span> <span class="kw">const</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">11</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(11.1)</a></span>
<code>is_convertible_v&lt;const SizeType&amp;, size_type&gt;</code> is
<code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(11.2)</a></span>
<code>is_nothrow_constructible_v&lt;size_type, const SizeType&amp;&gt;</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(11.3)</a></span>
<code>rank() == N</code> is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">12</a></span>
<em>Effects:</em> Let <code>P</code> be the parameter pack such that
<code>is_same_v&lt;make_index_sequence&lt;rank()&gt;, index_sequence&lt;P...&gt;&gt;</code>
is <code>true</code>. <br /> Equivalent to:
<code>return operator[](static_cast&lt;size_type&gt;(indices[P])...);</code></p>
<div class="sourceCode" id="cb46"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> size_type size<span class="op">()</span> <span class="kw">const</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">13</a></span>
<em>Precondition:</em> The size of <code>extents()</code> is a
representable value of <code>size_type</code> ([basic.fundamental]).</p>
<p><span class="marginalizedparent"><a class="marginalized">14</a></span>
<em>Returns:</em>
<code>extents().</code><em><code>fwd-prod-of-extents</code></em><code>(rank())</code>.</p>
<div class="sourceCode" id="cb47"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherElementType, <span class="kw">class</span> OtherExtents,</span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> OtherLayoutType, <span class="kw">class</span> OtherAccessorType<span class="op">&gt;</span></span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">operator</span> mdspan <span class="op">()</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">15</a></span>
<em>Constraints:</em>
<code>is_assignable_&lt;mdspan&lt;element_type, extents_type, layout_type&gt;, mdspan&lt;OtherElementType, OtherExtents, OtherLayoutType, OtherAccessorType&gt;&gt;</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">16</a></span>
<em>Returns:</em>
<code>mdspan(data(),</code><em><code>map_</code></em>)`</p>
<h1 data-number="5" id="references"><span class="header-section-number">5</span> References<a href="#references" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body" role="doc-bibliography">
<div id="ref-P0009R9" class="csl-entry" role="doc-biblioentry">
<div class="csl-left-margin">[P0009R9] </div><div class="csl-right-inline">H. Carter Edwards, Bryce Adelstein Lelbach,
Daniel Sunderland, David Hollman, Christian Trott, Mauro Bianco, Ben
Sander, Athanasios Iliopoulos, John Michopoulos, Mark Hoemmen. 2019.
mdspan: A Non-Owning Multidimensional Array Reference. <a href="https://wg21.link/p0009r9"><div class="csl-block">https://wg21.link/p0009r9</div></a></div>
</div>
</div>
</div>
</div>
</body>
</html>
