<!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="2023-05-19" />
  <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 { } 
code span.al { color: #ff0000; } 
code span.an { } 
code span.at { } 
code span.bn { color: #9f6807; } 
code span.bu { color: #9f6807; } 
code span.cf { color: #00607c; } 
code span.ch { color: #9f6807; } 
code span.cn { } 
code span.co { color: #008000; font-style: italic; } 
code span.cv { color: #008000; font-style: italic; } 
code span.do { color: #008000; } 
code span.dt { color: #00607c; } 
code span.dv { color: #9f6807; } 
code span.er { color: #ff0000; font-weight: bold; } 
code span.ex { } 
code span.fl { color: #9f6807; } 
code span.fu { } 
code span.im { } 
code span.in { color: #008000; } 
code span.kw { color: #00607c; } 
code span.op { color: #af1915; } 
code span.ot { } 
code span.pp { color: #6f4e37; } 
code span.re { } 
code span.sc { color: #9f6807; } 
code span.ss { color: #9f6807; } 
code span.st { color: #9f6807; } 
code span.va { } 
code span.vs { color: #9f6807; } 
code span.wa { color: #008000; font-weight: bold; } 
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:text/html; charset=utf-8;charset=utf-8,%3Chtml%3E%0A%3Chead%3E%0A%3Ctitle%3EBIG%2DIP%20Per%20Request%20Policy%20Resource%20blocked%20page%3C%2Ftitle%3E%0A%3Cstyle%3E%0Abody%2C%20html%20%7B%0A%20%20%20%20padding%3A%200%3B%0A%20%20%20%20margin%3A%200%3B%0A%20%20%20%20height%3A%20100%25%3B%0A%7D%0Atable%2C%20td%2C%20th%2C%20div%20%7B%0A%20%20%20%20border%3A%200%3B%0A%20%20%20%20padding%3A%200%3B%0A%20%20%20%20margin%3A%200%3B%0A%7D%0Abody%2C%20table%2C%20td%2C%20th%2C%20div%2C%20input%2C%20h1%2C%20h2%2C%20h3%2C%20h4%2C%20h5%2C%20h6%20%7B%0A%20%20%20%20font%2Dfamily%20%3A%20Calibri%2C%20Tahoma%2C%20Verdana%2C%20Arial%2C%20Helvetica%2C%20Sans%2DSerif%3B%0A%20%20%20%20color%3A%20%23000000%3B%0A%20%20%20%20text%2Dalign%3A%20center%3B%0A%7D%0Abody%2C%20table%2C%20td%2C%20th%2C%20div%2C%20input%20%7B%0A%20%20%20%20font%2Dsize%20%3A%2014px%3B%0A%7D%0Ah1%2C%20h2%2C%20h3%2C%20h4%2C%20h5%2C%20h6%20%7B%0A%20%20%20%20font%2Dsize%20%3A%2018px%3B%0A%20%20%20%20text%2Ddecoration%3A%20none%3B%0A%20%20%20%20margin%2Dbottom%3A%200px%3B%0A%7D%0Abody%0A%7B%0A%20%20%20%20background%2Dcolor%3A%20%23FFFFFF%3B%0A%7D%0Atable%23page%5Fheader%0A%7B%0A%20%20%20%20width%3A%20100%25%3B%0A%20%20%20%20height%3A%2080px%3B%0A%20%20%20%20background%2Dcolor%3A%20%23FFFFFF%3B%0A%20%20%20%20background%2Drepeat%3A%20repeat%2Dx%3B%0A%7D%0Atable%23main%5Ftable%0A%7B%0A%20%20%20%20width%3A100%25%3B%0A%7D%0A%3C%2Fstyle%3E%0A%3C%2Fhead%3E%0A%0A%3Cscript%20language%3D%22javascript%22%3E%0Afunction%20OnLoad%28%29%20%7B%0A%20%20%20%20var%20category%20%3D%20%22Information%20Technology%22%3B%0A%20%20%20%20var%20categoryDiv%20%3D%20document%2EgetElementById%28%27display%5Fcategory%27%29%3B%0A%20%20%20%20if%20%28category%20%3D%3D%3D%20%22%22%29%20%7B%0A%20%20%20%20%20%20%20%20categoryDiv%2Estyle%2Evisibility%20%3D%20%27hidden%27%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20categoryDiv%2Estyle%2Evisibility%20%3D%20%27visible%27%3B%0A%20%20%20%20%20%20%20%20categoryDiv%2EinnerHTML%20%2B%3D%20%27%3Ctd%3E%27%20%2B%20%22The%20category%20reference%20is%3A%22%20%2B%20%27%20%27%20%2B%20category%20%2B%20%27%3C%2Ftd%3E%27%3B%0A%20%20%20%20%7D%0A%7D%0A%3C%2Fscript%3E%0A%3Cbody%20onload%3D%22OnLoad%28%29%3B%22%3E%0A%20%20%20%20%3Ctable%20id%3D%22page%5Fheader%22%3E%0A%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%20style%3D%22padding%2Dleft%3A10px%3B%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Ch1%3ETransparent%20proxy%20access%20blocked%2E%20%3Cbr%3E%20Please%20verify%20your%20proxy%20setting%20are%20correct%2E%20%3Cbr%3E%20Contact%20CCHD%20if%20you%20need%20assistance%2E%3C%2Fh1%3E%20%20%20%20%20%20%20%20%3C%2Ftd%3E%3C%2Ftr%3E%0A%20%20%20%20%3C%2Ftable%3E%0A%20%20%20%20%3Ctable%20id%3D%27main%5Ftable%27%3E%0A%20%20%20%20%20%20%20%20%3Ctr%20id%3D%27display%5Fcategory%27%3E%3C%2Ftr%3E%0A%20%20%20%20%3C%2Ftable%3E%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A" 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>P1684R5</td>
  </tr>
  <tr>
    <td>Date: </td>
    <td>2023-05-19</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>
      Daisy Hollman<br>&lt;<a href="mailto:me@dsh.fyi" class="email">me@dsh.fyi</a>&gt;<br>
      Mark Hoemmen<br>&lt;<a href="mailto:mark.hoemmen@gmail.com" class="email">mark.hoemmen@gmail.com</a>&gt;<br>
      Daniel Sunderland<br>&lt;<a href="mailto:dansunderland@gmail.com" class="email">dansunderland@gmail.com</a>&gt;<br>
      Damien Lebrun-Grandie<br>&lt;<a href="mailto:lebrungrandt@ornl.gov" class="email">lebrungrandt@ornl.gov</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" id="toc-revision-history"><span class="toc-section-number">1</span> Revision History</a>
<ul>
<li><a href="#p1684r5-2023-05-mailing" id="toc-p1684r5-2023-05-mailing"><span class="toc-section-number">1.1</span> P1684R5: 2023-05 Mailing</a></li>
<li><a href="#p1684r4-2023-01-mailing" id="toc-p1684r4-2023-01-mailing"><span class="toc-section-number">1.2</span> P1684R4: 2023-01 Mailing</a></li>
<li><a href="#p1684r3-2022-07-mailing" id="toc-p1684r3-2022-07-mailing"><span class="toc-section-number">1.3</span> P1684R3: 2022-07 Mailing</a></li>
<li><a href="#p1684r2-2022-04-mailing" id="toc-p1684r2-2022-04-mailing"><span class="toc-section-number">1.4</span> P1684r2: 2022-04 Mailing</a></li>
<li><a href="#p1684r1-2022-03-mailing" id="toc-p1684r1-2022-03-mailing"><span class="toc-section-number">1.5</span> P1684r1: 2022-03 Mailing</a></li>
</ul></li>
<li><a href="#motivation" id="toc-motivation"><span class="toc-section-number">2</span> Motivation</a></li>
<li><a href="#design" id="toc-design"><span class="toc-section-number">3</span> Design</a>
<ul>
<li><a href="#design-overview" id="toc-design-overview"><span class="toc-section-number">3.1</span> Design overview</a></li>
<li><a href="#differences-between-mdarray-and-mdspan" id="toc-differences-between-mdarray-and-mdspan"><span class="toc-section-number">3.2</span> Differences between
<code>mdarray</code> and <code>mdspan</code></a>
<ul>
<li><a href="#deep-constness" id="toc-deep-constness"><span class="toc-section-number">3.2.1</span> Deep
<code>const</code>ness</a></li>
<li><a href="#interoperability-between-mdarray-and-mdspan" id="toc-interoperability-between-mdarray-and-mdspan"><span class="toc-section-number">3.2.2</span> Interoperability between
<code>mdarray</code> and <code>mdspan</code></a></li>
<li><a href="#container-instead-of-accessorpolicy" id="toc-container-instead-of-accessorpolicy"><span class="toc-section-number">3.2.3</span> <code>Container</code> instead
of <code>AccessorPolicy</code></a></li>
<li><a href="#constructors-and-assignment-operators" id="toc-constructors-and-assignment-operators"><span class="toc-section-number">3.2.4</span> Constructors and assignment
operators</a></li>
</ul></li>
<li><a href="#extents-design-reused" id="toc-extents-design-reused"><span class="toc-section-number">3.3</span> <code>Extents</code> design
reused</a></li>
<li><a href="#layoutpolicy-design-reused" id="toc-layoutpolicy-design-reused"><span class="toc-section-number">3.4</span> <code>LayoutPolicy</code> design
reused</a></li>
<li><a href="#accessorpolicy-replaced-by-container" id="toc-accessorpolicy-replaced-by-container"><span class="toc-section-number">3.5</span> <code>AccessorPolicy</code>
replaced by <code>Container</code></a>
<ul>
<li><a href="#expected-behavior-of-motivating-use-cases" id="toc-expected-behavior-of-motivating-use-cases"><span class="toc-section-number">3.5.1</span> Expected behavior of motivating
use cases</a></li>
<li><a href="#analogs-in-the-standard-library-container-adapters" id="toc-analogs-in-the-standard-library-container-adapters"><span class="toc-section-number">3.5.2</span> Analogs in the standard library:
Container adapters</a></li>
<li><a href="#not-proposed-alternative-a-dedicated-containerpolicy-concept" id="toc-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</a></li>
<li><a href="#not-proposed-alternative-containerpolicy-subsumes-accessorpolicy" id="toc-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></a></li>
<li><a href="#extension-for-accessor-policy-from-container" id="toc-extension-for-accessor-policy-from-container"><span class="toc-section-number">3.5.5</span> Extension for accessor policy
from container</a></li>
<li><a href="#safety-and-other-issues-with-containers" id="toc-safety-and-other-issues-with-containers"><span class="toc-section-number">3.5.6</span> Safety and other issues with
containers</a></li>
</ul></li>
</ul></li>
<li><a href="#constructor-overload-set-considerations" id="toc-constructor-overload-set-considerations"><span class="toc-section-number">4</span> Constructor Overload Set
Considerations</a>
<ul>
<li><a href="#current-argument-combinations" id="toc-current-argument-combinations"><span class="toc-section-number">4.1</span> Current Argument
combinations</a></li>
<li><a href="#minimal-alternative" id="toc-minimal-alternative"><span class="toc-section-number">4.2</span> Minimal Alternative</a></li>
<li><a href="#variadic" id="toc-variadic"><span class="toc-section-number">4.3</span> Variadic</a></li>
<li><a href="#overview-table" id="toc-overview-table"><span class="toc-section-number">4.4</span> Overview Table</a></li>
</ul></li>
<li><a href="#move-behavior" id="toc-move-behavior"><span class="toc-section-number">5</span> Move Behavior</a></li>
<li><a href="#wording" id="toc-wording"><span class="toc-section-number">6</span> Wording</a></li>
<li><a href="#acknowledgements" id="toc-acknowledgements"><span class="toc-section-number">7</span> Acknowledgements</a></li>
<li><a href="#references" id="toc-references"><span class="toc-section-number">8</span> References</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="p1684r5-2023-05-mailing"><span class="header-section-number">1.1</span> P1684R5: 2023-05 Mailing<a href="#p1684r5-2023-05-mailing" class="self-link"></a></h2>
<ul>
<li>discuss constructor overload set options</li>
<li>remove constructors taking container and integral packs</li>
<li>swap constructor arguments, extents/mapping should come before
container</li>
<li>disambiguate deduction guides</li>
<li>add precondition to relevant functions about container size being
large enough: this fixes issues in moved-from state</li>
<li>add function <code>extract_container</code> to move the container
out of <code>mdarray</code></li>
<li>rename <code>data()</code> to <code>container_data()</code> and add
<code>container_size()</code>
<ul>
<li><code>data()</code> did actually not go together with
<code>size()</code> for example for non-unique layouts</li>
<li>in moved from state <code>data()</code> also may not work together
with <code>mapping().required_span_size()</code>.</li>
</ul></li>
<li>work around the fact that <code>data()</code> and
<code>pointer</code> is not a thing required by contiguous container
requirements …</li>
<li>fix <code>to_mdspan</code> and <code>mdspan</code> conversion
operator</li>
</ul>
<h2 data-number="1.2" id="p1684r4-2023-01-mailing"><span class="header-section-number">1.2</span> P1684R4: 2023-01 Mailing<a href="#p1684r4-2023-01-mailing" class="self-link"></a></h2>
<h4 data-number="1.2.0.1" id="changes-from-r3"><span class="header-section-number">1.2.0.1</span> Changes from R3<a href="#changes-from-r3" class="self-link"></a></h4>
<ul>
<li>drop the “size constructible container” requirements and simply use
preconditions on relevant constructors</li>
</ul>
<h2 data-number="1.3" id="p1684r3-2022-07-mailing"><span class="header-section-number">1.3</span> P1684R3: 2022-07 Mailing<a href="#p1684r3-2022-07-mailing" class="self-link"></a></h2>
<h4 data-number="1.3.0.1" id="changes-from-r2"><span class="header-section-number">1.3.0.1</span> Changes from R2<a href="#changes-from-r2" class="self-link"></a></h4>
<ul>
<li>bring in line with P0009 and follow up papers P2554, P2553, P2599
and P2406</li>
<li>add new container requirements: <em>size constructible
containers</em> (bikeshedding needed)</li>
<li>add deduction guide for <code>mdspan</code> from
<code>mdarray</code></li>
<li>remove constructors from
<code>ranges</code>/<code>initializer_list</code> etc. (can be done via
moving container in)
<ul>
<li>waiting for feedback from other sgs to see which convenience
constructors we should have</li>
</ul></li>
<li>add deduction guides</li>
<li>update explanatory wording</li>
</ul>
<h2 data-number="1.4" id="p1684r2-2022-04-mailing"><span class="header-section-number">1.4</span> P1684r2: 2022-04 Mailing<a href="#p1684r2-2022-04-mailing" class="self-link"></a></h2>
<h4 data-number="1.4.0.1" id="changes-from-r1"><span class="header-section-number">1.4.0.1</span> Changes from R1<a href="#changes-from-r1" class="self-link"></a></h4>
<ul>
<li>update and reword non-wording text to harmonize with P0009R16</li>
<li>fix synopsis missing Alloc argument in some places</li>
<li>fix constraints on some constructors to allow
<code>std::array</code> as container</li>
<li>add missing wording for constructors from
<code>std::initializer_list</code></li>
<li>add constructors from ranges</li>
<li>always use <code>std::vector</code> as the default container type,
based on LEWG guidance</li>
<li>remove container accessor function
<ul>
<li>it’s a bad idea to allow someone to resize the container owned by an
<code>mdarray</code> …</li>
</ul></li>
<li>add new <code>mdarray</code> constructors from
<code>mdspan</code></li>
<li>add <code>view</code> member function; it returns an
<code>mdspan</code> that views the <code>mdarray</code>’s elements</li>
</ul>
<h2 data-number="1.5" id="p1684r1-2022-03-mailing"><span class="header-section-number">1.5</span> P1684r1: 2022-03 Mailing<a href="#p1684r1-2022-03-mailing" class="self-link"></a></h2>
<h4 data-number="1.5.0.1" id="changes-from-r0"><span class="header-section-number">1.5.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="P0009R18">[<a href="#ref-P0009R18" role="doc-biblioref"><strong>P0009R18?</strong></a>]</span> proposed
<code>mdspan</code>, a nonowning multidimensional array abstraction. It
was voted into the C++23 draft. This proposal builds on
<code>mdspan</code> by introducing <code>mdarray</code>, an
<em>owning</em> multidimensional array that interoperates with
<code>mdspan</code>. The <code>mdarray</code> class is to
<code>vector</code> as <code>mdspan</code> is to <code>span</code>.
Owning semantics can make it easier for users to express common cases,
like returning an array from a function. It also makes it much easier to
create a multi dimensional array for use:</p>
<p><strong>C++23:</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="co">// Create a mapping so one knows how many </span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="co">// elements the buffer needs to have</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>layout_right<span class="op">::</span>mapping<span class="op">&lt;</span>dextents<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">2</span><span class="op">&gt;&gt;</span> map<span class="op">(</span>N,M<span class="op">)</span>;</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="co">// Create the underlying data object</span></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>vector<span class="op">&lt;</span><span class="dt">double</span><span class="op">&gt;</span> buffer<span class="op">(</span>map<span class="op">.</span>required_span_size<span class="op">())</span>;</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="co">// Create the mdspan</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>mdspan matrix<span class="op">(</span>buffer<span class="op">.</span>data<span class="op">()</span>, N, M<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">double</span>, dextents<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">2</span><span class="op">&gt;&gt;</span> matrix<span class="op">(</span>N,M<span class="op">)</span>;</span></code></pre></div>
<p>In addition, especially for arrays with small, compile-time extents,
<code>mdarray</code>’s owning semantics make fewer demands on
interprocedural analysis for optimization. In particular, the lack of
indirection due to <code>mdarray</code> owning its data makes it easier
for compilers to deduce that the data could be stored in registers.</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, with the goals of
reducing cognitive load for users already familiar with
<code>mdspan</code> and of incorporating the lessons learned from over a
decade of experience with <span class="citation" data-cites="P0009R18">[<a href="#ref-P0009R18" role="doc-biblioref"><strong>P0009R18?</strong></a>]</span> and
libraries of similar design. This paper assumes the reader has read and
is already familiar with <span class="citation" data-cites="P0009R18">[<a href="#ref-P0009R18" role="doc-biblioref"><strong>P0009R18?</strong></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>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="P0009R18">[<a href="#ref-P0009R18" role="doc-biblioref"><strong>P0009R18?</strong></a>]</span>, which has
the following 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> default_accessor<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>Our original <code>mdarray</code> proposal <span class="citation" data-cites="P1684R0">[<a href="#ref-P1684R0" role="doc-biblioref">P1684R0</a>]</span> had a
<code>ContainerPolicy</code> instead of a <code>Container</code>
template parameter. The <code>ContainerPolicy</code> provided
functionality like that of <code>mdspan</code>’s
<code>AccessorPolicy</code>, and would also select the actual container
type used to store the <code>mdarray</code>’s data.</p>
<p>For the current revision of this proposal, we have decided that the
complexity of a <code>ContainerPolicy</code> 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 that are better served by
<code>mdspan</code>. For example, one might have code that creates and
uses an <code>mdarray</code> in several different ways. One loop over
the array might have write conflicts that an atomic accessor would
resolve. Changing how one views data in a way limited to a particular
context is the job of a view. That is, in this case, it would make the
most sense to create a temporary <code>mdspan</code> with an atomic
accessor that views the original <code>mdarray</code>, for use in the
particular loop that needs atomic access.</p>
<h2 data-number="3.2" id="differences-between-mdarray-and-mdspan"><span class="header-section-number">3.2</span> Differences between
<code>mdarray</code> and <code>mdspan</code><a href="#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 calls for a
few differences.</p>
<h3 data-number="3.2.1" id="deep-constness"><span class="header-section-number">3.2.1</span> Deep <code>const</code>ness<a href="#deep-constness" class="self-link"></a></h3>
<p>The most notable difference from <code>mdspan</code> 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 as data_handle_type:</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>
<h3 data-number="3.2.2" id="interoperability-between-mdarray-and-mdspan"><span class="header-section-number">3.2.2</span> Interoperability between
<code>mdarray</code> and <code>mdspan</code><a href="#interoperability-between-mdarray-and-mdspan" class="self-link"></a></h3>
<p>The <code>mdarray</code> class 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>. One way we could do this would be by
adding a constructor to <code>mdspan</code>. This which would be more
consistent with the analogous features in <code>span</code> and
<code>string_view</code>. However, in the interest of avoiding
modifications to an in-flight proposal, we instead propose using a
member function of <code>mdarray</code> for this functionality for now.
This member function is tentatively named <code>to_mdspan()</code>, but
we welcome suggestions for other names.</p>
<p>One advantage of this member function is that it could serve as a
starting point for a general customization point in C++ for obtaining an
<code>mdspan</code> generically. <code>to_mdspan</code> would
effectively work like <code>begin</code> and other such customization
points, which allow C++ facilities to interact with user provided
classes.</p>
<p>We would be 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> mdspan_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_mdspan_type <span class="op">=</span> <span class="co">/* ... */</span>;</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OT, <span class="kw">class</span> OE, <span class="kw">class</span> OL, <span class="kw">class</span> OA<span class="op">&gt;</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>    <span class="kw">operator</span> mdspan<span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherAccessorType <span class="op">=</span> default_accessor<span class="op">&lt;</span>element_type<span class="op">&gt;&gt;</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> to_mdspan<span class="op">(</span><span class="kw">const</span> OtherAccessorType<span class="op">&amp;</span> a <span class="op">=</span> </span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a>                     default_accessor<span class="op">&lt;</span>element_type<span class="op">&gt;())</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherAccessorType <span class="op">=</span> default_accessor<span class="op">&lt;</span><span class="kw">const</span> element_type<span class="op">&gt;&gt;</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a>    <span class="kw">auto</span> to_mdspan<span class="op">(</span><span class="kw">const</span> OtherAccessorType<span class="op">&amp;</span> a <span class="op">=</span> </span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a>                     default_accessor<span class="op">&lt;</span><span class="kw">const</span> element_type<span class="op">&gt;())</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h3 data-number="3.2.3" id="container-instead-of-accessorpolicy"><span class="header-section-number">3.2.3</span> <code>Container</code>
instead of <code>AccessorPolicy</code><a href="#container-instead-of-accessorpolicy" class="self-link"></a></h3>
<p>As we discuss elsewhere, the <code>mdspan</code> class has an
<code>AccessorPolicy</code> template parameter, while
<code>mdarray</code> has a <code>Container</code> template
parameter.</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> Container<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_type <span class="op">=</span> Container;</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<h3 data-number="3.2.4" id="constructors-and-assignment-operators"><span class="header-section-number">3.2.4</span> Constructors and assignment
operators<a href="#constructors-and-assignment-operators" class="self-link"></a></h3>
<p>The constructors and assignment operators of <code>mdspan</code> and
<code>mdarray</code> have a few differences. The <code>mdspan</code>
class 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> does not need a <code>pointer</code> 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 deep-copy the input container.</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>Moreover, containers such as <code>vector</code> and container
adapters like <code>queue</code> have a significant number of other
constructors which copy the data on input, such as constructors taking
ranges, input iterator pairs, and initializer lists. The R2 version of
this paper had a number of those, but in combination with allocator
arguments it lead to an explosion of constructors. A draft version seen
by LEWG on 2022-07-12 sported 41 constructors. However almost all these
constructors would simply forward arguments to the constructor of the
container owned by <code>mdarray</code>. LEWG provided feedback that we
should consider reducing the amount of constructors, since at a minimum
one could inline construct the <code>container</code> itself, and move
it into the <code>mdarray</code> upon construction.</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="co">// with convenience constructors:</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>mdarray a<span class="op">(</span>first, last, N, M<span class="op">)</span>;</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="co">// without</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>mdarray a<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>vector<span class="op">(</span>first, last<span class="op">))</span>, N, M<span class="op">)</span>;</span></code></pre></div>
<p>In R3 we decided to radically cut back on constructors and simply
leave those out.</p>
<p>Finally, <code>mdarray</code> does not have the analog of
<code>mdspan</code>’s constructor that takes an
<code>array&lt;IndexType, N&gt;</code> of dynamic extents. This avoids
any 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="P0009R18">[<a href="#ref-P0009R18" role="doc-biblioref"><strong>P0009R18?</strong></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
pieces are perhaps a less perfect fit are the
<code>is_contiguous()</code> and <code>is_always_contiguous()</code>
requirements. While noncontiguous use cases for <code>mdspan</code> are
quite common (e.g., <code>subspan()</code>), noncontiguous 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 designed for nonowning semantics. 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="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>, <span class="dv">3</span><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>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="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">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="cb14-2"><a href="#cb14-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 nonowning). We provisionally call the method
for taking a view of an <code>mdarray</code>
“<code>to_mdspan()</code>”:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">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="cb15-2"><a href="#cb15-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="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">auto</span> data_view <span class="op">=</span> data<span class="op">.</span>to_mdspan<span class="op">()</span>;</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb15-6"><a href="#cb15-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="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> T, <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="cb16-2"><a href="#cb16-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, Container<span class="op">&gt;</span> a<span class="op">)</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>  mdspan a_view<span class="op">(</span>a<span class="op">.</span>data<span class="op">()</span>, a<span class="op">.</span>mapping<span class="op">())</span>;</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></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 (that is, 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="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ElementType,</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> Extents,</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> LayoutPolicy,</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>         <span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> mdarray <span class="op">{</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a> <span class="co">/* ... */</span></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a> mdspan<span class="op">&lt;</span></span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>   ElementType, Extents, LayoutPolicy,</span>
<span id="cb17-9"><a href="#cb17-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="cb17-10"><a href="#cb17-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="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a> <span class="co">/* ... */</span></span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-14"><a href="#cb17-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="cb17-15"><a href="#cb17-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="cb17-16"><a href="#cb17-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="cb17-17"><a href="#cb17-17" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb17-18"><a href="#cb17-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="cb17-19"><a href="#cb17-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="cb17-20"><a href="#cb17-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="cb17-21"><a href="#cb17-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb17-22"><a href="#cb17-22" aria-hidden="true" tabindex="-1"></a>  <span class="co">/* ... */</span></span>
<span id="cb17-23"><a href="#cb17-23" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span></code></pre></div>
<p>However, this approach comes at the cost of an additional
indirection: one for the pointer to the container, and one for the
container dereference itself. This 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>submdspan</code>) is potentially even worse for arbitrary
non-contiguous containers, adding up to one indirection per invocation
of <code>submdspan</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. This is 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 straightforward way to resolve the above concerns with arbitrary
container types, is to simply restrict what type of containers can be
used. Specifically, we would restrict it such that creating an
<code>mdspan</code> with <code>default_accessor</code> is
straightforward. Thus we would require
<code>decltype(Container::data())</code> to denote
<code>ElementType*</code>, and <code>&amp;c[i]</code> to equal
<code>c.data() + i</code> for all <code>i</code> in the range of <span class="math inline">[</span><code>0</code>, <code>c.size()</code><span class="math inline">)</span>.</p>
<p>In what follows, 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="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> 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="cb18-2"><a href="#cb18-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="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> element_type <span class="op">=</span> ElementType;</span>
<span id="cb18-6"><a href="#cb18-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="cb18-7"><a href="#cb18-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="cb18-8"><a href="#cb18-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="cb18-9"><a href="#cb18-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="cb18-10"><a href="#cb18-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="cb18-11"><a href="#cb18-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="cb18-12"><a href="#cb18-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="cb18-13"><a href="#cb18-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="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a>  <span class="co">// analogous to `access` method in `AccessorPolicy`</span></span>
<span id="cb18-16"><a href="#cb18-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="cb18-17"><a href="#cb18-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="cb18-18"><a href="#cb18-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-19"><a href="#cb18-19" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Interface for mdspan creation</span></span>
<span id="cb18-20"><a href="#cb18-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="cb18-21"><a href="#cb18-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="cb18-22"><a href="#cb18-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="cb18-23"><a href="#cb18-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="cb18-24"><a href="#cb18-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-25"><a href="#cb18-25" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Interface for sized construction</span></span>
<span id="cb18-26"><a href="#cb18-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="cb18-27"><a href="#cb18-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="cb18-28"><a href="#cb18-28" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb18-29"><a href="#cb18-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="cb18-30"><a href="#cb18-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="cb18-31"><a href="#cb18-31" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb18-32"><a href="#cb18-32" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-33"><a href="#cb18-33" aria-hidden="true" tabindex="-1"></a>  container_type __c;</span>
<span id="cb18-34"><a href="#cb18-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 nonowning 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="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_policy <span class="co">// models ContainerPolicy (and thus AccessorPolicy)</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> offset_policy <span class="op">=</span> vector_container_policy<span class="op">&lt;</span>ElementType, Allocator<span class="op">&gt;</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ContainerPolicy requirements:</span></span>
<span id="cb19-15"><a href="#cb19-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="cb19-16"><a href="#cb19-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="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ContainerPolicy requirements (interface for sized construction):</span></span>
<span id="cb19-19"><a href="#cb19-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="cb19-20"><a href="#cb19-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="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb19-22"><a href="#cb19-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="cb19-23"><a href="#cb19-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="cb19-24"><a href="#cb19-24" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb19-25"><a href="#cb19-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-26"><a href="#cb19-26" aria-hidden="true" tabindex="-1"></a>  <span class="co">// AccessorPolicy requirement:</span></span>
<span id="cb19-27"><a href="#cb19-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="cb19-28"><a href="#cb19-28" aria-hidden="true" tabindex="-1"></a>  <span class="co">// For the const analog of AccessorPolicy:</span></span>
<span id="cb19-29"><a href="#cb19-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="cb19-30"><a href="#cb19-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-31"><a href="#cb19-31" aria-hidden="true" tabindex="-1"></a>  <span class="co">// AccessorPolicy requirement:</span></span>
<span id="cb19-32"><a href="#cb19-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="cb19-33"><a href="#cb19-33" aria-hidden="true" tabindex="-1"></a>  <span class="co">// For the const analog of AccessorPolicy:</span></span>
<span id="cb19-34"><a href="#cb19-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="cb19-35"><a href="#cb19-35" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-36"><a href="#cb19-36" aria-hidden="true" tabindex="-1"></a>  <span class="co">// AccessorPolicy requirement:</span></span>
<span id="cb19-37"><a href="#cb19-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="cb19-38"><a href="#cb19-38" aria-hidden="true" tabindex="-1"></a>  <span class="co">// For the const analog of AccessorPolicy:</span></span>
<span id="cb19-39"><a href="#cb19-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="cb19-40"><a href="#cb19-40" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-41"><a href="#cb19-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="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>ContainerPolicy P<span class="op">&gt;</span></span>
<span id="cb20-2"><a href="#cb20-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="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb20-4"><a href="#cb20-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="cb20-5"><a href="#cb20-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="cb20-6"><a href="#cb20-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="cb20-7"><a href="#cb20-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="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-9"><a href="#cb20-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="cb20-10"><a href="#cb20-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="cb20-11"><a href="#cb20-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="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb20-14"><a href="#cb20-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="cb20-15"><a href="#cb20-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>
<h3 data-number="3.5.5" id="extension-for-accessor-policy-from-container"><span class="header-section-number">3.5.5</span> Extension for accessor policy
from container<a href="#extension-for-accessor-policy-from-container" class="self-link"></a></h3>
<p>Most of the drawbacks of using container directly as the template
parameter for <code>mdarray</code> addressed in the above design
alternatives, can likely be remedied by introducing a customization
point to obtain an accessor policy and the associated
<code>data_handle</code> from an existing container. We do not propose
such a customization point in this paper, but don’t expect this to be a
major issue.</p>
<h3 data-number="3.5.6" id="safety-and-other-issues-with-containers"><span class="header-section-number">3.5.6</span> Safety and other issues with
containers<a href="#safety-and-other-issues-with-containers" class="self-link"></a></h3>
<h4 data-number="3.5.6.1" id="size-and-access-guarantees-for-containers"><span class="header-section-number">3.5.6.1</span> Size and access guarantees
for containers<a href="#size-and-access-guarantees-for-containers" class="self-link"></a></h4>
<p>We have to somehow guarantee that containers constructed from sizes
(or if such constructors are reintroduced from iterator pairs,
initializer lists or ranges), are actually large enough after the
construction so we can index into them. However, we don’t want full
sequence container requirements (also there is no named requirement for
a constructor which takes an integral only).</p>
<p>To illustrate the problem consider a user defined container with a
static size but that has a constructor which takes an init value.</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>user<span class="op">::</span>static_vector<span class="op">&lt;</span><span class="dt">int</span>, <span class="dv">200</span><span class="op">&gt;</span> vec<span class="op">(</span><span class="dv">1000</span><span class="op">)</span>;</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a><span class="ot">assert</span><span class="op">(</span>vec<span class="op">.</span>size<span class="op">()==</span><span class="dv">200</span><span class="op">)</span>;</span></code></pre></div>
<p>From the perspective of <code>mdarray</code> this container looks
like its constructible from a size, but that is not actually what the
container does.</p>
<p>We previously proposed a new set of named optional requirements for
containers which guarantee the desired behavior.</p>
<p>These requirements would need to go into the general container
requirements, or be a new named requirement? But maybe there is also
another way to require these semantics for containers used with
<code>mdarray</code> instead, for example one might say it is undefined
behavior if a container class is used which does not have a size of
<code>n</code> when constructed with <code>n</code> as its sole
argument.</p>
<p>In Revision 4 we removed those named container requirements and
instead propose an alternative approach - made easier by the removal of
a lot of constructors in R3. Specifically, we enforce that containers
constructed from sizes have that expected size via preconditions on the
relevant containers.</p>
<h4 data-number="3.5.6.2" id="size-requirements-for-construction-from-containers-etc."><span class="header-section-number">3.5.6.2</span> Size requirements for
construction from containers etc.<a href="#size-requirements-for-construction-from-containers-etc." class="self-link"></a></h4>
<p>We explicitly require that if an <code>mdarray</code> is constructed
from some existing set of elements (container, iterators, range, etc.),
that the size of that container etc. is larger or equal to the mappings
required span size. The larger or equal is intentional, because the
mapping may already be not exhaustive. I.e. the <code>mdarray</code> may
not end up accessing all elements in its own container. But in that case
it is not clear why having unused elements at the end should be
different from having unused elements somewhere else in the
container.</p>
<h1 data-number="4" id="constructor-overload-set-considerations"><span class="header-section-number">4</span> Constructor Overload Set
Considerations<a href="#constructor-overload-set-considerations" class="self-link"></a></h1>
<p>As discussed before, there are numerous options of how to design the
constructor overlaod set for <code>mdarray</code>. Compared to other
containers and container adaptors the situation is more complicated, due
to the combinatorical nature of having the layout mapping arguments with
the common set of container arguments (values, allocators, ranges
etc.).</p>
<p>A prior version of this paper had well over 40 constructor overloads.
The current version still has on the order of 20, but we believe that it
is the best compromise between complexity and usability. We put the
emphasis on easy usability in most common cases, while preserving
clarity of behavior. There are two alternatives we considered based on
received feedback:</p>
<ul>
<li>A minimal approach just providing the extents/mapping overloads and
versions of it which take a container</li>
<li>A variadic approach with perfect forwarding of arguments to the
internal container constructor.</li>
</ul>
<p>All variants have the converting constructors, and also the
constructors from mdspan in addition to the combinations listed
here.</p>
<h2 data-number="4.1" id="current-argument-combinations"><span class="header-section-number">4.1</span> Current Argument combinations<a href="#current-argument-combinations" class="self-link"></a></h2>
<p>This set is almost the same as in the previous revision of the paper,
however we removed an overload taking a container and integrals, which
allowed us to change the order for constructors taking a container, so
that the extents or mapping argument is always first.</p>
<ul>
<li>Integrals</li>
<li>extents</li>
<li>mapping</li>
<li>extents + value</li>
<li>mapping + value</li>
<li>extents + container</li>
<li>mapping + container</li>
<li>extents + allocator</li>
<li>mapping + allocator</li>
<li>extents + value + allocator</li>
<li>mapping + value + allocator</li>
<li>extents + container + allocator</li>
<li>mapping + container + allocator</li>
</ul>
<p>Note that this set does not include a constructor from iterators or
ranges these can be written by passing in an immediate constructed
container:</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>mdarray<span class="op">&lt;...&gt;</span> a<span class="op">(</span>extents<span class="op">{...}</span>, vector<span class="op">{</span>begin, end<span class="op">})</span>;</span></code></pre></div>
<h2 data-number="4.2" id="minimal-alternative"><span class="header-section-number">4.2</span> Minimal Alternative<a href="#minimal-alternative" class="self-link"></a></h2>
<p>A question which came up is whether, it would be sufficient to always
wrap things in a container and pass that in, for example for the use
case of providing an allocator, or constructing an <code>mdarray</code>
with a value to fill. This would reduce the acceptable argument set to
this:</p>
<ul>
<li>Integrals</li>
<li>extents</li>
<li>mapping</li>
<li>extents + container</li>
<li>mapping + container</li>
</ul>
<p>However, it would make some common use cases very verbose to write
when using values or allocators, due to the need to compute the size of
the container. Constructing with a fill value would become this:</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>some_mdarray_t a<span class="op">(</span>extents<span class="op">{...}</span>, vector<span class="op">(</span>layout_right<span class="op">::</span>mapping<span class="op">{</span>extents<span class="op">{...}}.</span>required_span_size<span class="op">()</span>, value<span class="op">))</span>;</span></code></pre></div>
<p>instead of</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>some_mdarray_t a<span class="op">(</span>extents<span class="op">{...}</span>, value<span class="op">)</span>;</span></code></pre></div>
<h2 data-number="4.3" id="variadic"><span class="header-section-number">4.3</span> Variadic<a href="#variadic" class="self-link"></a></h2>
<p>Yet another considered alternative would rely on argument forwarding
by providing a constructor with variadic templates:</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> <span class="op">...</span> Args<span class="op">&gt;</span></span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">(</span>extents_type, Args<span class="op">&amp;&amp;</span> <span class="op">...)</span>;</span></code></pre></div>
<p>This would reduce the overload set (other than conversion and from
<code>mdspan</code>) to this:</p>
<ul>
<li>Integrals</li>
<li>extents</li>
<li>mapping</li>
<li>extents + container-ctor-args</li>
<li>mapping + container-ctor-args</li>
</ul>
<p>However, using this approach results in some awkward and hard to
understand situations. To begin with, the constructor actually has two
situations. In order to support the following:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>some_mdarray_t a<span class="op">(</span>extents<span class="op">{...}</span>, value<span class="op">)</span>;</span></code></pre></div>
<p>The constructor needs to check whether the container is constructible
from a size and the provided arguments. Besides the value case this is
important for the usecase of providing an allocator.</p>
<p>However, that leads to an unfortunate situation depending on the
container type and its scalar type.</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">&lt;</span><span class="dt">float</span>, dextents<span class="op">&lt;</span><span class="dt">int</span>,<span class="dv">2</span><span class="op">&gt;&gt;</span> a<span class="op">(</span>extents<span class="op">{</span><span class="dv">10</span>, <span class="dv">10</span><span class="op">}</span>, <span class="dv">200</span><span class="op">)</span>;</span></code></pre></div>
<p>creates a rank-2 mdarray where every value will be set to 200.</p>
<p>On the other hand:</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">&lt;</span>pair<span class="op">&lt;</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">&gt;</span>, dextents<span class="op">&lt;</span><span class="dt">int</span>,<span class="dv">2</span><span class="op">&gt;&gt;</span> a<span class="op">(</span>extents<span class="op">{</span><span class="dv">10</span>, <span class="dv">10</span><span class="op">}</span>, <span class="dv">200</span><span class="op">)</span>;</span></code></pre></div>
<p>creates a rank-2 mdarray with an underlying container of size 200,
and the values are default initialized. If one would to use 99 instead
of 200, this second constructor would have a precondition violation,
because the constructor arguments result in container of too small
size.</p>
<p>We believe that this situation is not tenable, and should be
avoided.</p>
<h2 data-number="4.4" id="overview-table"><span class="header-section-number">4.4</span> Overview Table<a href="#overview-table" class="self-link"></a></h2>
<p>The following table gives an overview of the three approaches. In
this table we use these shorthands:</p>
<ul>
<li><code>mda_t</code>: a specialization of <code>mdarray</code></li>
<li><code>c_t</code>: the <code>container_type</code> of
<code>mda_t</code></li>
<li><code>e</code>: an <code>extents</code> object</li>
<li><code>m</code>: a layout mapping object</li>
<li><code>me</code>: a <code>extents</code> object or a layout mapping
object</li>
<li><code>c</code>: an instance of <code>c_t</code></li>
<li><code>a</code>: an allocator object</li>
<li><code>v</code>: a value (something convertible to
<code>mda_t::value_type</code></li>
<li><code>mda</code>: an <code>mdarray</code> object, not necessarily
the same type as <code>mda_t</code></li>
<li><code>mds</code>: an <code>mdspan</code> obejct, not necessarily the
same as returned by <code>mda_t::to_mdspan</code></li>
</ul>
<table>
<thead>
<tr>
<th>
Arguments
</th>
<th>
Current
</th>
<th>
Minimal
</th>
<th>
Variadic
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>default</code>
</td>
<td>
<code>mda_t()</code>
</td>
<td>
<code>mda_t()</code>
</td>
<td>
<code>mda_t()</code>
</td>
</tr>
<tr>
<td>
integrals
</td>
<td>
<code>mda_t(10, 10)</code>
</td>
<td>
<code>mda_t(10, 10)</code>
</td>
<td>
<code>mda_t(10, 10)</code>
</td>
</tr>
<tr>
<td>
mapping/extents
</td>
<td>
<code>mda_t(me)</code>
</td>
<td>
<code>mda_t(me)</code>
</td>
<td>
<code>mda_t(me)</code>
</td>
</tr>
<tr>
<td>
container + integrals
</td>
<td>
<code>mda_t(extents{10, 10}, c)</code>
</td>
<td>
<code>mda_t(extents{10, 10}, c)</code>
</td>
<td>
<code>mda_t(extents{10, 10}, c)</code>
</td>
</tr>
<tr>
<td>
move container + integrals
</td>
<td>
<code>mda_t(extents{10, 10}, move(c))</code>
</td>
<td>
<code>mda_t(extents{10, 10}, move(c))</code>
</td>
<td>
<code>mda_t(extents{10, 10}, move(c))</code>
</td>
</tr>
<tr>
<td>
container + mapping/extents
</td>
<td>
<code>mda_t(me, c)</code>
</td>
<td>
<code>mda_t(me, c)</code>
</td>
<td>
<code>mda_t(me, c)</code>
</td>
</tr>
<tr>
<td>
move container + mapping
</td>
<td>
<code>mda_t(me, move(c))</code>
</td>
<td>
<code>mda_t(me, move(c))</code>
</td>
<td>
<code>mda_t(me, move(c))</code>
</td>
</tr>
<td>
container + alloc + mapping/extents
</td>
<td>
<code>mda_t(me, c, a)</code>
</td>
<td>
<code>mda_t(me, c_t(c,a))</code>
</td>
<td>
<code>mda_t(me, c, a)</code>
</td>
</tr>
<tr>
<td>
move container + alloc + mapping
</td>
<td>
<code>mda_t(me, move(c), a)</code>
</td>
<td>
<code>mda_t(me, c_t(move(c),a))</code>
</td>
<td>
<code>mda_t(me, move(c), a)</code>
</td>
</tr>
<tr>
<td>
extents + value
</td>
<td>
<code>mda_t(e, v)</code>
</td>
<td>
<code>mda_t(e, c_t(map_t(e).required_span_size(), v))</code>
</td>
<td>
<code>mda_t(e, v)</code>
</td>
</tr>
<tr>
<td>
mapping + value
</td>
<td>
<code>mda_t(m, v)</code>
</td>
<td>
<code>mda_t(m, c_t(m.required_span_size(), v))</code>
</td>
<td>
<code>mda_t(m, v)</code>
</td>
</tr>
<tr>
<td>
mapping + custom container size
</td>
<td>
<code>mda_t(m, c_t(s))</code>
</td>
<td>
<code>mda_t(m, c_t(s))</code>
</td>
<td>
<code>mda_t(m, c_t(s))</code> or <code>mda_t(m, s)</code> for integrals
not convertible to <code>value_type</code>
</td>
</tr>
<tr>
<td>
mapping + custom container size + value
</td>
<td>
<code>mda_t(m, c_t(s, v))</code>
</td>
<td>
<code>mda_t(m, c_t(s, v))</code>
</td>
<td>
<code>mda_t(m, s, v)</code>
</td>
</tr>
<tr>
<td>
extents + value + alloc
</td>
<td>
<code>mda_t(e, v, a)</code>
</td>
<td>
<code>mda_t(e, c_t(map_t(e).required_span_size(), v, a)))</code>
</td>
<td>
<code>mda_t(e, v , a)</code>
</td>
</tr>
<tr>
<td>
mapping + value + alloc
</td>
<td>
<code>mda_t(m, v, a)</code>
</td>
<td>
<code>mda_t(m, move(c_t(m.required_span_size(), v, a)))</code>
</td>
<td>
<code>mda_t(m, v, a)</code>
</td>
</tr>
<tr>
<td>
mapping + custom container size + alloc
</td>
<td>
<code>mda_t(m, c_t(s, a))</code>
</td>
<td>
<code>mda_t(m, c_t(s, a))</code>
</td>
<td>
<code>mda_t(m, c_t(s, a))</code> or <code>mda_t(m, s, a)</code> for
integrals not convertible to <code>value_type</code>
</td>
</tr>
<tr>
<td>
mapping + custom container size + value + alloc
</td>
<td>
<code>mda_t(m, c_t(s, v, a))</code>
</td>
<td>
<code>mda_t(m, c_t(s, v, a))</code>
</td>
<td>
<code>mda_t(m, s, v, a)</code>
</td>
</tr>
<tr>
<td>
iterators
</td>
<td>
<code>mda_t(m, c_t(begin, end))</code>
</td>
<td>
<code>mda_t(m, c_t(begin, end))</code>
</td>
<td>
<code>mda_t(m, begin, end)</code>
</td>
</tr>
<tr>
<td>
range
</td>
<td>
<code>mda_t(m, c_t(r))</code>
</td>
<td>
<code>mda_t(m, c_t(r))</code>
</td>
<td>
<code>mda_t(m, r)</code>
</td>
</tr>
<tr>
<td>
converting mdarray
</td>
<td>
<code>mda_t(mda)</code>
</td>
<td>
<code>mda_t(mda)</code>
</td>
<td>
<code>mda_t(mda)</code>
</td>
</tr>
<tr>
<td>
compatible mdspan
</td>
<td>
<code>mda_t(mds)</code>
</td>
<td>
<code>mda_t(mds)</code>
</td>
<td>
<code>mda_t(mds)</code>
</td>
</tr>
<td>
compatible mdspan + allocator
</td>
<td>
<code>mda_t(mds, a)</code>
</td>
<td>
<code>mda_t(mds, a)</code>
</td>
<td>
<code>mda_t(mds, a)</code>
</td>
</tr>
</tbody>
</table>
<h1 data-number="5" id="move-behavior"><span class="header-section-number">5</span> Move Behavior<a href="#move-behavior" class="self-link"></a></h1>
<p>We considered various strategies to deal with move behavior of
<code>mdarray</code> in a way that the invariants are guaranteed, or at
a minimum no invalid operation can happen without a user checkable
precondition.</p>
<p>There are three primary options:</p>
<ul>
<li>add preconditions to relevant operations which will check that the
containers size is still large enough</li>
<li>don’t provide any move semantics for <code>mdarray</code></li>
<li>add a bool member which tracks whether <code>mdarray</code> was
moved from</li>
</ul>
<p>We believe that the first option is preferrable at this point, since
it introduces the least new concepts. Move semantics for
<code>mdarray</code> - in particular of <code>mdarray</code> with
<code>array</code> container type and static extents - are very
valuable. Adding an extra member likely also makes the small static-size
<code>mdarray</code> case produce less optimal code.</p>
<p>We did consider requiring emptying out the container in conjunction
with option 1, but believe that is not necessary and adds undesirable
overhead for custom container use cases.</p>
<p>In order to make the new precondition testable by users, we introduce
an observer of the underlying container’s size.</p>
<h1 data-number="6" id="wording"><span class="header-section-number">6</span> Wording<a href="#wording" class="self-link"></a></h1>
<p><br /></p>
<p>Insert the following after section 24.6.6</p>
<p><b>24.6.� Class template <code>mdarray</code> [mdarray]</b></p>
<p><br /></p>
<p><b>24.6.�.1 <code>mdarray</code> overview [mdarray.overview]</b></p>
<p><span class="marginalizedparent"><a class="marginalized">1</a></span>
<code>mdarray</code> is a multidimensional array of elements.</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="kw">namespace</span> std <span class="op">{</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="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="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a>         vector<span class="op">&lt;</span>ElementType<span class="op">&gt;&gt;</span></span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> mdarray <span class="op">{</span></span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> extents_type <span class="op">=</span> Extents;</span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> layout_type <span class="op">=</span> LayoutPolicy;</span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> container_type <span class="op">=</span> Container;</span>
<span id="cb29-10"><a href="#cb29-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="cb29-11"><a href="#cb29-11" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> element_type <span class="op">=</span> ElementType;</span>
<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> mdspan_type <span class="op">=</span> mdspan<span class="op">&lt;</span>element_type, extents_type, layout_type<span class="op">&gt;</span>;</span>
<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_mdspan_type <span class="op">=</span> mdspan<span class="op">&lt;</span><span class="kw">const</span> element_type, extents_type, layout_type<span class="op">&gt;</span>;</span>
<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> value_type <span class="op">=</span> element_type;</span>
<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> index_type <span class="op">=</span> <span class="kw">typename</span> Extents<span class="op">::</span>index_type;</span>
<span id="cb29-16"><a href="#cb29-16" 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="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> rank_type <span class="op">=</span> <span class="kw">typename</span> Extents<span class="op">::</span>rank_type;</span>
<span id="cb29-18"><a href="#cb29-18" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> pointer <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span>to_address<span class="op">(</span>declval<span class="op">&lt;</span>container_type<span class="op">&gt;().</span>begin<span class="op">()))</span>;</span>
<span id="cb29-19"><a href="#cb29-19" 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="cb29-20"><a href="#cb29-20" aria-hidden="true" tabindex="-1"></a>  <span class="kw">using</span> const_pointer <span class="op">=</span> <span class="kw">decltype</span><span class="op">(</span>to_address<span class="op">(</span>declval<span class="op">&lt;</span>container_type<span class="op">&gt;().</span>cbegin<span class="op">()))</span>;</span>
<span id="cb29-21"><a href="#cb29-21" 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="cb29-22"><a href="#cb29-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-23"><a href="#cb29-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> rank_type rank<span class="op">()</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> extents_type<span class="op">::</span>rank<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb29-24"><a href="#cb29-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> rank_type rank_dynamic<span class="op">()</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> extents_type<span class="op">::</span>rank_dynamic<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb29-25"><a href="#cb29-25" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">size_t</span> static_extent<span class="op">(</span>rank_type r<span class="op">)</span> <span class="kw">noexcept</span></span>
<span id="cb29-26"><a href="#cb29-26" aria-hidden="true" tabindex="-1"></a>    <span class="op">{</span> <span class="cf">return</span> extents_type<span class="op">::</span>static_extent<span class="op">(</span>r<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb29-27"><a href="#cb29-27" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> index_type extent<span class="op">(</span>rank_type r<span class="op">)</span> <span class="kw">const</span> <span class="kw">noexcept</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="cb29-28"><a href="#cb29-28" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-29"><a href="#cb29-29" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [mdarray.ctors], mdarray constructors</span></span>
<span id="cb29-30"><a href="#cb29-30" 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="cb29-31"><a href="#cb29-31" 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="cb29-32"><a href="#cb29-32" 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="cb29-33"><a href="#cb29-33" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-34"><a href="#cb29-34" 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> OtherIndexTypes<span class="op">&gt;</span></span>
<span id="cb29-35"><a href="#cb29-35" aria-hidden="true" tabindex="-1"></a>    <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span>OtherIndexTypes<span class="op">...</span> exts<span class="op">)</span>;</span>
<span id="cb29-36"><a href="#cb29-36" 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> extents_type<span class="op">&amp;</span> ext<span class="op">)</span>;</span>
<span id="cb29-37"><a href="#cb29-37" 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> m<span class="op">)</span>;</span>
<span id="cb29-38"><a href="#cb29-38" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-39"><a href="#cb29-39" 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> value_type<span class="op">&amp;</span> val<span class="op">)</span>;</span>
<span id="cb29-40"><a href="#cb29-40" 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> value_type<span class="op">&amp;</span> val<span class="op">)</span>;</span>
<span id="cb29-41"><a href="#cb29-41" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-42"><a href="#cb29-42" 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> container_type<span class="op">&amp;</span> c<span class="op">)</span>;</span>
<span id="cb29-43"><a href="#cb29-43" 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> container_type<span class="op">&amp;</span> c,<span class="op">)</span>;</span>
<span id="cb29-44"><a href="#cb29-44" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-45"><a href="#cb29-45" 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, container_type<span class="op">&amp;&amp;</span> c<span class="op">)</span>;</span>
<span id="cb29-46"><a href="#cb29-46" 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, container_type<span class="op">&amp;&amp;</span> c,<span class="op">)</span>;</span>
<span id="cb29-47"><a href="#cb29-47" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-48"><a href="#cb29-48" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-49"><a href="#cb29-49" 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="cb29-50"><a href="#cb29-50" 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="cb29-51"><a href="#cb29-51" 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="cb29-52"><a href="#cb29-52" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span></span>
<span id="cb29-53"><a href="#cb29-53" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> mdarray<span class="op">&lt;</span>OtherElementType, OtherExtents,</span>
<span id="cb29-54"><a href="#cb29-54" aria-hidden="true" tabindex="-1"></a>                    OtherLayoutPolicy, OtherContainer<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span>
<span id="cb29-55"><a href="#cb29-55" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-56"><a href="#cb29-56" 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="cb29-57"><a href="#cb29-57" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> OtherLayoutPolicy, <span class="kw">class</span> Accessor<span class="op">&gt;</span></span>
<span id="cb29-58"><a href="#cb29-58" 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="cb29-59"><a href="#cb29-59" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mdspan<span class="op">&lt;</span>OtherElementType, OtherExtents,</span>
<span id="cb29-60"><a href="#cb29-60" aria-hidden="true" tabindex="-1"></a>                                   OtherLayoutPolicy, Accessor<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span>
<span id="cb29-61"><a href="#cb29-61" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-62"><a href="#cb29-62" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [mdarray.ctors.alloc], mdarray constructors with allocators</span></span>
<span id="cb29-63"><a href="#cb29-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="cb29-64"><a href="#cb29-64" 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>
<span id="cb29-65"><a href="#cb29-65" 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="cb29-66"><a href="#cb29-66" 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="cb29-67"><a href="#cb29-67" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-68"><a href="#cb29-68" 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="cb29-69"><a href="#cb29-69" 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> value_type<span class="op">&amp;</span> val, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span>
<span id="cb29-70"><a href="#cb29-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="cb29-71"><a href="#cb29-71" 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> value_type<span class="op">&amp;</span> val, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span>
<span id="cb29-72"><a href="#cb29-72" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-73"><a href="#cb29-73" 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="cb29-74"><a href="#cb29-74" 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> container_type<span class="op">&amp;</span> c, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span>
<span id="cb29-75"><a href="#cb29-75" 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="cb29-76"><a href="#cb29-76" 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> container_type<span class="op">&amp;</span> c, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span>
<span id="cb29-77"><a href="#cb29-77" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-78"><a href="#cb29-78" 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="cb29-79"><a href="#cb29-79" 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, container_type<span class="op">&amp;&amp;</span> c, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span>
<span id="cb29-80"><a href="#cb29-80" 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="cb29-81"><a href="#cb29-81" 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, container_type<span class="op">&amp;&amp;</span> c, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span>
<span id="cb29-82"><a href="#cb29-82" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-83"><a href="#cb29-83" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-84"><a href="#cb29-84" 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="cb29-85"><a href="#cb29-85" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> OtherLayoutPolicy, <span class="kw">class</span> OtherContainer, </span>
<span id="cb29-86"><a href="#cb29-86" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb29-87"><a href="#cb29-87" 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="cb29-88"><a href="#cb29-88" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span></span>
<span id="cb29-89"><a href="#cb29-89" aria-hidden="true" tabindex="-1"></a>      <span class="kw">const</span> mdarray<span class="op">&lt;</span>OtherElementType, OtherExtents, </span>
<span id="cb29-90"><a href="#cb29-90" aria-hidden="true" tabindex="-1"></a>                    OtherLayoutPolicy, OtherContainer<span class="op">&gt;&amp;</span> other, <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span>
<span id="cb29-91"><a href="#cb29-91" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-92"><a href="#cb29-92" 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="cb29-93"><a href="#cb29-93" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> OtherLayoutPolicy, <span class="kw">class</span> Accessor,</span>
<span id="cb29-94"><a href="#cb29-94" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb29-95"><a href="#cb29-95" 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="cb29-96"><a href="#cb29-96" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mdspan<span class="op">&lt;</span>OtherElementType, OtherExtents,</span>
<span id="cb29-97"><a href="#cb29-97" aria-hidden="true" tabindex="-1"></a>                                   OtherLayoutPolicy, Accessor<span class="op">&gt;&amp;</span> other,</span>
<span id="cb29-98"><a href="#cb29-98" aria-hidden="true" tabindex="-1"></a>                      <span class="kw">const</span> Alloc<span class="op">&amp;</span> a<span class="op">)</span>;</span>
<span id="cb29-99"><a href="#cb29-99" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-100"><a href="#cb29-100" 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="cb29-101"><a href="#cb29-101" 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="cb29-102"><a href="#cb29-102" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-103"><a href="#cb29-103" aria-hidden="true" tabindex="-1"></a>  <span class="co">// [mdarray.members], mdarray members</span></span>
<span id="cb29-104"><a href="#cb29-104" 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> OtherIndexTypes<span class="op">&gt;</span></span>
<span id="cb29-105"><a href="#cb29-105" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> reference <span class="kw">operator</span><span class="op">[](</span>OtherIndexTypes<span class="op">...</span> indices<span class="op">)</span>;</span>
<span id="cb29-106"><a href="#cb29-106" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherIndexType<span class="op">&gt;</span></span>
<span id="cb29-107"><a href="#cb29-107" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> reference <span class="kw">operator</span><span class="op">[](</span>span<span class="op">&lt;</span>OtherIndexType, rank<span class="op">()&gt;</span> indices<span class="op">)</span>;</span>
<span id="cb29-108"><a href="#cb29-108" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherIndexType<span class="op">&gt;</span></span>
<span id="cb29-109"><a href="#cb29-109" 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>OtherIndexType, rank<span class="op">()&gt;&amp;</span> indices<span class="op">)</span>;</span>
<span id="cb29-110"><a href="#cb29-110" 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> OtherIndexTypes<span class="op">&gt;</span></span>
<span id="cb29-111"><a href="#cb29-111" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> const_reference <span class="kw">operator</span><span class="op">[](</span>OtherIndexTypes<span class="op">...</span> indices<span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb29-112"><a href="#cb29-112" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherIndexType<span class="op">&gt;</span></span>
<span id="cb29-113"><a href="#cb29-113" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> const_reference <span class="kw">operator</span><span class="op">[](</span>span<span class="op">&lt;</span>OtherIndexType, rank<span class="op">()&gt;</span> indices<span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb29-114"><a href="#cb29-114" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherIndexType<span class="op">&gt;</span></span>
<span id="cb29-115"><a href="#cb29-115" 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>OtherIndexType, rank<span class="op">()&gt;&amp;</span> indices<span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb29-116"><a href="#cb29-116" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-117"><a href="#cb29-117" 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="cb29-118"><a href="#cb29-118" aria-hidden="true" tabindex="-1"></a>  <span class="op">[[</span><span class="at">nodiscard</span><span class="op">]]</span> <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span>
<span id="cb29-119"><a href="#cb29-119" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">auto</span> container_size<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> ctr_<span class="op">.</span>size<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb29-120"><a href="#cb29-120" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-121"><a href="#cb29-121" aria-hidden="true" tabindex="-1"></a>  <span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">void</span> swap<span class="op">(</span>mdarray<span class="op">&amp;</span> x, mdarray<span class="op">&amp;</span> y<span class="op">)</span> <span class="kw">noexcept</span>;</span>
<span id="cb29-122"><a href="#cb29-122" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-123"><a href="#cb29-123" 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="cb29-124"><a href="#cb29-124" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> pointer container_data<span class="op">()</span>; <span class="op">{</span> <span class="cf">return</span> to_address<span class="op">(</span><em>ctr_</em><span class="op">.</span>begin<span class="op">())</span>; <span class="op">}</span></span>
<span id="cb29-125"><a href="#cb29-125" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> const_pointer container_data<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> to_address<span class="op">(</span><em>ctr_</em><span class="op">.</span>cbegin<span class="op">())</span>; <span class="op">}</span></span>
<span id="cb29-126"><a href="#cb29-126" 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="cb29-127"><a href="#cb29-127" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-128"><a href="#cb29-128" 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="cb29-129"><a href="#cb29-129" 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="cb29-130"><a href="#cb29-130" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="kw">operator</span> mdspan <span class="op">()</span> <span class="kw">const</span>;</span>
<span id="cb29-131"><a href="#cb29-131" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-132"><a href="#cb29-132" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherAccessorType <span class="op">=</span> default_accessor<span class="op">&lt;</span>element_type<span class="op">&gt;&gt;</span></span>
<span id="cb29-133"><a href="#cb29-133" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdspan<span class="op">&lt;</span>element_type, extents_type, layout_type, OtherAccessorType<span class="op">&gt;</span></span>
<span id="cb29-134"><a href="#cb29-134" aria-hidden="true" tabindex="-1"></a>      to_mdspan<span class="op">(</span><span class="kw">const</span> OtherAccessorType<span class="op">&amp;</span> a <span class="op">=</span> default_accessor<span class="op">&lt;</span>element_type<span class="op">&gt;())</span>;</span>
<span id="cb29-135"><a href="#cb29-135" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherAccessorType <span class="op">=</span> default_accessor<span class="op">&lt;</span><span class="kw">const</span> element_type<span class="op">&gt;&gt;</span></span>
<span id="cb29-136"><a href="#cb29-136" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdspan<span class="op">&lt;</span><span class="kw">const</span> element_type, extents_type, layout_type, OtherAccessorType<span class="op">&gt;</span></span>
<span id="cb29-137"><a href="#cb29-137" aria-hidden="true" tabindex="-1"></a>      to_mdspan<span class="op">(</span><span class="kw">const</span> OtherAccessorType<span class="op">&amp;</span> a <span class="op">=</span> default_accessor<span class="op">&lt;</span>const_element_type<span class="op">&gt;())</span> <span class="kw">const</span>;</span>
<span id="cb29-138"><a href="#cb29-138" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-139"><a href="#cb29-139" aria-hidden="true" tabindex="-1"></a>  container_type<span class="op">&amp;&amp;</span> extract_container<span class="op">()</span> <span class="op">&amp;&amp;</span> <span class="op">{</span> <span class="cf">return</span> std<span class="op">::</span>move<span class="op">(</span><em>ctr_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb29-140"><a href="#cb29-140" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-141"><a href="#cb29-141" 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="cb29-142"><a href="#cb29-142" 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="cb29-143"><a href="#cb29-143" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-144"><a href="#cb29-144" aria-hidden="true" tabindex="-1"></a>  <span class="kw">static</span> <span class="kw">constexpr</span> <span class="dt">bool</span> is_always_exhaustive<span class="op">()</span> <span class="op">{</span></span>
<span id="cb29-145"><a href="#cb29-145" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> mapping_type<span class="op">::</span>is_always_exhaustive<span class="op">()</span>;</span>
<span id="cb29-146"><a href="#cb29-146" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-147"><a href="#cb29-147" 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="cb29-148"><a href="#cb29-148" 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="cb29-149"><a href="#cb29-149" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-150"><a href="#cb29-150" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-151"><a href="#cb29-151" 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="cb29-152"><a href="#cb29-152" 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="cb29-153"><a href="#cb29-153" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-154"><a href="#cb29-154" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> <span class="dt">bool</span> is_exhaustive<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span></span>
<span id="cb29-155"><a href="#cb29-155" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <em>map_</em><span class="op">.</span>is_exhaustive<span class="op">()</span>;</span>
<span id="cb29-156"><a href="#cb29-156" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-157"><a href="#cb29-157" 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="cb29-158"><a href="#cb29-158" 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="cb29-159"><a href="#cb29-159" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-160"><a href="#cb29-160" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> index_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="cb29-161"><a href="#cb29-161" 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="cb29-162"><a href="#cb29-162" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb29-163"><a href="#cb29-163" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-164"><a href="#cb29-164" aria-hidden="true" tabindex="-1"></a><span class="kw">private</span><span class="op">:</span></span>
<span id="cb29-165"><a href="#cb29-165" aria-hidden="true" tabindex="-1"></a>  container_type ctr_;</span>
<span id="cb29-166"><a href="#cb29-166" aria-hidden="true" tabindex="-1"></a>  mapping_type <em>map_</em>; <span class="co">// <em>exposition only</em></span></span>
<span id="cb29-167"><a href="#cb29-167" aria-hidden="true" tabindex="-1"></a><span class="op">}</span>;</span>
<span id="cb29-168"><a href="#cb29-168" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-169"><a href="#cb29-169" 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> <span class="op">...</span> Extents, <span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb29-170"><a href="#cb29-170" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">(</span><span class="kw">const</span> extents<span class="op">&lt;</span>IndexType, Extents<span class="op">...&gt;&amp;</span>, <span class="kw">const</span> Container<span class="op">&amp;)</span></span>
<span id="cb29-171"><a href="#cb29-171" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> mdarray<span class="op">&lt;</span><span class="kw">typename</span> Container<span class="op">::</span>value_type, extents<span class="op">&lt;</span>IndexType, Extents<span class="op">...&gt;</span>, layout_right, Container<span class="op">&gt;</span>;</span>
<span id="cb29-172"><a href="#cb29-172" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-173"><a href="#cb29-173" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Mapping, <span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb29-174"><a href="#cb29-174" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">(</span><span class="kw">const</span> Mapping<span class="op">&amp;</span>, <span class="kw">const</span> Container<span class="op">&amp;)</span></span>
<span id="cb29-175"><a href="#cb29-175" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> mdarray<span class="op">&lt;</span><span class="kw">typename</span> Container<span class="op">::</span>value_type, <span class="kw">typename</span> Mapping<span class="op">::</span>extents_type, <span class="kw">typename</span> Mapping<span class="op">::</span>layout_type, Container<span class="op">&gt;</span>;</span>
<span id="cb29-176"><a href="#cb29-176" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-177"><a href="#cb29-177" 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> <span class="op">...</span> Extents, <span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb29-178"><a href="#cb29-178" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">(</span><span class="kw">const</span> extents<span class="op">&lt;</span>IndexType, Extents<span class="op">...&gt;&amp;</span>, Container<span class="op">&amp;&amp;)</span></span>
<span id="cb29-179"><a href="#cb29-179" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> mdarray<span class="op">&lt;</span><span class="kw">typename</span> Container<span class="op">::</span>value_type, extents<span class="op">&lt;</span>IndexType, Extents<span class="op">...&gt;</span>, layout_right, Container<span class="op">&gt;</span>;</span>
<span id="cb29-180"><a href="#cb29-180" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-181"><a href="#cb29-181" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Mapping, <span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb29-182"><a href="#cb29-182" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">(</span><span class="kw">const</span> Mapping<span class="op">&amp;</span>, Container<span class="op">&amp;&amp;)</span></span>
<span id="cb29-183"><a href="#cb29-183" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> mdarray<span class="op">&lt;</span><span class="kw">typename</span> Container<span class="op">::</span>value_type, <span class="kw">typename</span> Mapping<span class="op">::</span>extents_type, <span class="kw">typename</span> Mapping<span class="op">::</span>layout_type, Container<span class="op">&gt;</span>;</span>
<span id="cb29-184"><a href="#cb29-184" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-185"><a href="#cb29-185" 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> Layout, <span class="kw">class</span> Accessor<span class="op">&gt;</span></span>
<span id="cb29-186"><a href="#cb29-186" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">(</span><span class="kw">const</span> mdspan<span class="op">&lt;</span>ElementType, Extents, Layout, Accessor<span class="op">&gt;&amp;)</span></span>
<span id="cb29-187"><a href="#cb29-187" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> mdarray<span class="op">&lt;</span>remove_cv_t<span class="op">&lt;</span>ElementType<span class="op">&gt;</span>, Extents, Layout<span class="op">&gt;</span>;</span>
<span id="cb29-188"><a href="#cb29-188" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-189"><a href="#cb29-189" 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> <span class="op">...</span> Extents, <span class="kw">class</span> Container, <span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb29-190"><a href="#cb29-190" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">(</span><span class="kw">const</span> extents<span class="op">&lt;</span>IndexType, Extents<span class="op">...&gt;&amp;</span>, <span class="kw">const</span> Container<span class="op">&amp;</span>, <span class="kw">const</span> Alloc<span class="op">&amp;)</span></span>
<span id="cb29-191"><a href="#cb29-191" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> mdarray<span class="op">&lt;</span><span class="kw">typename</span> Container<span class="op">::</span>value_type, extents<span class="op">&lt;</span>IndexType, Extents<span class="op">...&gt;</span>, layout_right, Container<span class="op">&gt;</span>;</span>
<span id="cb29-192"><a href="#cb29-192" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-193"><a href="#cb29-193" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Mapping, <span class="kw">class</span> Container, <span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb29-194"><a href="#cb29-194" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">(</span><span class="kw">const</span> Mapping<span class="op">&amp;</span>, <span class="kw">const</span> Container<span class="op">&amp;</span>, <span class="kw">const</span> Alloc<span class="op">&amp;)</span></span>
<span id="cb29-195"><a href="#cb29-195" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> mdarray<span class="op">&lt;</span><span class="kw">typename</span> Container<span class="op">::</span>value_type, <span class="kw">typename</span> Mapping<span class="op">::</span>extents_type, <span class="kw">typename</span> Mapping<span class="op">::</span>layout_type, Container<span class="op">&gt;</span>;</span>
<span id="cb29-196"><a href="#cb29-196" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-197"><a href="#cb29-197" 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> <span class="op">...</span> Extents, <span class="kw">class</span> Container, <span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb29-198"><a href="#cb29-198" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">(</span><span class="kw">const</span> extents<span class="op">&lt;</span>IndexType, Extents<span class="op">...&gt;&amp;</span>, Container<span class="op">&amp;&amp;</span>, <span class="kw">const</span> Alloc<span class="op">&amp;)</span></span>
<span id="cb29-199"><a href="#cb29-199" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> mdarray<span class="op">&lt;</span><span class="kw">typename</span> Container<span class="op">::</span>value_type, extents<span class="op">&lt;</span>IndexType, Extents<span class="op">...&gt;</span>, layout_right, Container<span class="op">&gt;</span>;</span>
<span id="cb29-200"><a href="#cb29-200" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-201"><a href="#cb29-201" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> Mapping, <span class="kw">class</span> Container, <span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb29-202"><a href="#cb29-202" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">(</span><span class="kw">const</span> Mapping<span class="op">&amp;</span>, Container<span class="op">&amp;&amp;</span>, <span class="kw">const</span> Alloc<span class="op">&amp;)</span></span>
<span id="cb29-203"><a href="#cb29-203" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> mdarray<span class="op">&lt;</span><span class="kw">typename</span> Container<span class="op">::</span>value_type, <span class="kw">typename</span> Mapping<span class="op">::</span>extents_type, <span class="kw">typename</span> Mapping<span class="op">::</span>layout_type, Container<span class="op">&gt;</span>;</span>
<span id="cb29-204"><a href="#cb29-204" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb29-205"><a href="#cb29-205" 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> Layout, <span class="kw">class</span> Accessor, <span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb29-206"><a href="#cb29-206" aria-hidden="true" tabindex="-1"></a>mdarray<span class="op">(</span><span class="kw">const</span> mdspan<span class="op">&lt;</span>ElementType, Extents, Layout, Accessor<span class="op">&gt;&amp;</span>, <span class="kw">const</span> Alloc<span class="op">&amp;)</span></span>
<span id="cb29-207"><a href="#cb29-207" aria-hidden="true" tabindex="-1"></a>  <span class="op">-&gt;</span> mdarray<span class="op">&lt;</span>remove_cv_t<span class="op">&lt;</span>ElementType<span class="op">&gt;</span>, Extents, Layout<span class="op">&gt;</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">2</a></span>
<em>Mandates:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.1)</a></span>
<code>ElementType</code> is a a complete object type that is neither an
abstract class type nor an array type,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.2)</a></span>
<code>Extents</code> is a specialization of <code>extents</code>,
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.3)</a></span>
<code>is_same_v&lt;ElementType, typename Container::value_type&gt;</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<code>LayoutPolicy</code> shall meet the layout mapping policy
requirements [mdspan.layoutpolicy.reqmts], and</p>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<code>Container</code> shall meet the requirements of contiguous
container.</p>
<p><span class="marginalizedparent"><a class="marginalized">5</a></span>
Each specialization <code>MDA</code> of <code>mdarray</code> models
<code>copyable</code> and</p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.1)</a></span>
<code>is_nothrow_move_constructible_v&lt;MDA&gt;</code> is
<code>true</code> if
<code>is_nothrow_move_constructible_v&lt;Container&gt;</code> is
<code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.2)</a></span>
<code>is_nothrow_move_assignable_v&lt;MDA&gt;</code> is
<code>true</code> if
<code>is_nothrow_move_assignable_v&lt;Container&gt;</code> is
<code>true</code> , and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.3)</a></span>
<code>is_nothrow_swappable_v&lt;MDA&gt;</code> is <code>true</code> if
<code>is_nothrow_swappable_v&lt;Container&gt;</code> is
<code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
A specialization of <code>mdarray</code> is a trivially copyable type if
its <code>container_type</code> and <code>mapping_type</code> are
trivially copyable types.</p>
<p><b>24.6.�.2 Exposition only functions </b></p>
<div class="sourceCode" id="cb30"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ValueType, <span class="kw">class</span> Index<span class="op">&gt;</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="kw">decltype</span><span class="op">(</span><span class="kw">auto</span><span class="op">)</span> <em>just-value</em><span class="op">(</span>Index, ValueType<span class="op">&amp;&amp;</span> t<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> forward<span class="op">&lt;</span>ValueType<span class="op">&amp;&amp;&gt;(</span>t<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> ValueType, <span class="dt">size_t</span> N<span class="op">&gt;</span></span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>array<span class="op">&lt;</span>ValueType, N<span class="op">&gt;</span></span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a><em>value-to-array</em><span class="op">(</span><span class="kw">const</span> ValueType<span class="op">&amp;</span> t<span class="op">)</span></span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="op">[&amp;]&lt;</span><span class="dt">size_t</span> <span class="op">...</span> Indices<span class="op">&gt;(</span>index_sequence<span class="op">&lt;</span>Indices<span class="op">...&gt;)</span> <span class="op">{</span></span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> array<span class="op">&lt;</span>ValueType, N<span class="op">&gt;{</span> <em>just-value</em><span class="op">(</span>Indices, t<span class="op">)...</span> <span class="op">}</span>;</span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a>    <span class="op">}(</span> make_index_sequence<span class="op">&lt;</span>N<span class="op">&gt;()</span> <span class="op">)</span>;</span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<!--

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

-->
<p><b>24.6.�.2 <code>mdarray</code> constructors [mdarray.ctors]</b></p>
<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">template</span><span class="op">&lt;</span><span class="kw">class</span><span class="op">...</span> OtherIndexTypes<span class="op">&gt;</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> mdarray<span class="op">(</span>OtherIndexTypes<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;OtherIndexTypes, index_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;index_type, OtherIndexTypes&gt; &amp;&amp; ...)</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.3)</a></span>
<code>is_constructible_v&lt;extents_type, OtherIndexTypes...&gt;</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.4)</a></span>
<code>is_constructible_v&lt;mapping_type, extents_type&gt;</code> is
<code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.5)</a></span> if
<code>container_type</code> is not a specialization of
<code>array</code>,
<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>Preconditions:</em></p>
<ul>
<li><p>[2.1] Let <code>map</code> be
<code>mapping_type(extents_type(static_cast&lt;index_type&gt;(std::move(exts)...)))</code>,
then</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.2)</a></span> if
<code>container_type</code> is a specialization of <code>array</code>,
<code>map.required_span_size() &lt;= size(container_type())</code> is
<code>true</code>, otherwise</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.3)</a></span>
<code>map.required_span_size() &lt;= size(container_type(map.required_span_size()))</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>extents_type(static_cast&lt;index_type&gt;(std::move(exts))...)</code>,
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.2)</a></span> if
<code>is_constructible_v&lt;container_type, size_t&gt;</code> is
<code>true</code>, direct-non-list-initializes <code>ctr_</code> with
<code>container_type(</code><em><code>map_</code></em><code>.required_span_size())</code>,
otherwise default constructs <code>ctr_</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">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">4</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(4.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">(4.2)</a></span> if
<code>container_type</code> is not a specialization of
<code>array</code>,
<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">5</a></span>
<em>Preconditions:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.1)</a></span> Let
<code>map</code> be <code>mapping_type(ext)</code>, then</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.2)</a></span> if
<code>container_type</code> is a specialization of <code>array</code>,
<code>map.required_span_size() &lt;= size(container_type())</code> is
<code>true</code>, otherwise</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.3)</a></span>
<code>map.required_span_size() &lt;= size(container_type(map.required_span_size()))</code>
is <code>true</code>.</p></li>
</ul>
<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>ext</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(6.2)</a></span> if
<code>is_constructible_v&lt;container_type, size_t&gt;</code> is
<code>true</code>, direct-non-list-initializes <code>ctr_</code> with
<code>container_type(</code><em><code>map_</code></em><code>.required_span_size())</code>,
otherwise default constructs <code>ctr_</code>.</p></li>
</ul>
<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="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mapping_type<span class="op">&amp;</span> map<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<em>Constraints:</em> if <code>container_type</code> is not a
specialization of <code>array</code>,
<code>is_constructible_v&lt;container_type, size_t&gt;</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
<em>Preconditions:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(8.1)</a></span> if
<code>container_type</code> is a specialization of <code>array</code>,
<code>map.required_span_size() &lt;= size(container_type())</code> is
<code>true</code>, otherwise</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(8.2)</a></span>
<code>map.required_span_size() &lt;= size(container_type(map.required_span_size()))</code>
is <code>true</code>.</p></li>
</ul>
<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>map</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(9.2)</a></span> If
<code>is_constructible_v&lt;container_type, size_t&gt;</code> is
<code>true</code>, direct-non-list-initializes <code>ctr_</code> with
<code>container_type(</code><em><code>map_</code></em><code>.required_span_size())</code>,
otherwise default constructs <code>ctr_</code>.</p></li>
</ul>
<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">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> value_type<span class="op">&amp;</span> val<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">10</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(10.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">(10.2)</a></span> if
<code>container_type</code> is not a specialization of
<code>array</code>,
<code>is_constructible_v&lt;container_type, size_t, value_type&gt;</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">11</a></span>
<em>Preconditions:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(11.1)</a></span> Let
<code>map</code> be <code>mapping_type(ext)</code>, then</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(11.2)</a></span> if
<code>container_type</code> is a specialization of <code>array</code>,
<code>map.required_span_size() &lt;= size(container_type())</code> is
<code>true</code>, otherwise</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(11.3)</a></span>
<code>map.required_span_size() &lt;= size(container_type(map.required_span_size()))</code>
is <code>true</code>.</p></li>
</ul>
<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> if
<code>is_constructible_v&lt;container_type, size_t, value_type&gt;</code>
is <code>true</code>, direct-non-list-initializes <code>ctr_</code> with
<code>container_type(</code><em><code>map_</code></em><code>.required_span_size(), val)</code>,
otherwise direct-non-list-initializes <code>ctr_</code> with
<em><code>value-to-array</code></em><code>&lt;element_type, size(declval&lt;container_type&gt;())&gt;()</code>.</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">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> value_type<span class="op">&amp;</span> val<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">13</a></span>
<em>Constraints:</em> if <code>container_type</code> is not a
specialization of <code>array</code>,
<code>is_constructible_v&lt;container_type, size_t, value_type&gt;</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">14</a></span>
<em>Preconditions:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(14.1)</a></span> if
<code>container_type</code> is a specialization of <code>array</code>,
<code>map.required_span_size() &lt;= size(container_type())</code> is
<code>true</code>, otherwise</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(14.2)</a></span>
<code>map.required_span_size() &lt;= size(container_type(map.required_span_size(), val))</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">15</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(15.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">(15.2)</a></span> if
<code>is_constructible_v&lt;container_type, size_t, value_type&gt;</code>
is <code>true</code>, direct-non-list-initializes <code>ctr_</code> with
<code>container_type(</code><em><code>map_</code></em><code>.required_span_size(), val)</code>,
otherwise direct-non-list-initializes <code>ctr_</code> with
<em><code>value-to-array</code></em><code>&lt;element_type, size(declval&lt;container_type&gt;())&gt;()</code>.</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">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> container_type<span class="op">&amp;</span> c<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">14</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">15</a></span>
<em>Preconditions:</em>
<code>c.size() &gt;= mapping_type(ext).required_span_size()</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">16</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(16.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">(16.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>c</code>.</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">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> container_type<span class="op">&amp;</span> c<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">17</a></span>
<em>Preconditions:</em>
<code>c.size() &gt;= m.required_span_size()</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">18</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(18.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">(18.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>c</code>.</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">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> extents_type<span class="op">&amp;</span> ext, container_type<span class="op">&amp;&amp;</span> c<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">19</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">20</a></span>
<em>Preconditions:</em>
<code>c.size() &gt;= mapping_type(ext).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>ext</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(21.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>std::move(c)</code>.</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">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mapping_type<span class="op">&amp;</span> m, container_type<span class="op">&amp;&amp;</span> c<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">22</a></span>
<em>Preconditions:</em>
<code>c.size() &gt;= m.required_span_size()</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">23</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(23.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">(23.2)</a></span>
Direct-non-list-initializes <code>ctr_</code> with
<code>std::move(c)</code>.</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="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 class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">24</a></span>
<em>Mandates:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(24.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">(24.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">25</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(25.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">(25.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">26</a></span>
<em>Preconditions:</em> 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>.</p>
<p><span class="marginalizedparent"><a class="marginalized">27</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(27.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">(27.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">28</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>
<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> OtherElementType, <span class="kw">class</span> OtherExtents,</span>
<span id="cb42-2"><a href="#cb42-2" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> OtherLayoutPolicy, <span class="kw">class</span> Accessor<span class="op">&gt;</span></span>
<span id="cb42-3"><a href="#cb42-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="cb42-4"><a href="#cb42-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mdspan<span class="op">&lt;</span>OtherElementType, OtherExtents,</span>
<span id="cb42-5"><a href="#cb42-5" aria-hidden="true" tabindex="-1"></a>                                   OtherLayoutPolicy, Accessor<span class="op">&gt;&amp;</span> other<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">29</a></span>
<em>Mandates:</em>
<code>is_constructible_v&lt;extents_type, OtherExtents&gt;</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">30</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(30.1)</a></span>
<code>is_constructible_v&lt;value_type, Accessor::reference&gt;</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(30.2)</a></span>
<code>is_assignable_v&lt;Accessor::reference, value_type&gt;</code> is
<code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(30.3)</a></span>
<code>is_default_constructible_v&lt;value_type&gt;</code> is
<code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(30.4)</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">(30.5)</a></span> if
<code>container_type</code> is not a specialization of
<code>array</code>,
<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">31</a></span>
<em>Preconditions:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(31.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>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(31.2)</a></span> if
<code>container_type</code> is a specialization of <code>array</code>,
then
<code>container_type().size() &gt;= other.mapping().required_span_size()</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">32</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(32.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>other.mapping()</code>;</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(32.2)</a></span> If
<code>is_constructible_v&lt;container_type, size_t&gt;</code> is
<code>true</code>, direct-non-list-initializes <code>ctr_</code> with
<code>container_type(other.mapping().required_span_size())</code>,
otherwise default constructs <em><code>ctr_</code></em>; and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(32.3)</a></span> For
all unique multidimensional indices <code>i...</code> in
<code>other.extents()</code>, assigns <code>other[i...]</code> to
<code>ctr_[</code><em><code>map_</code></em><code>(i...)]</code>.</p></li>
</ul>
<p><i>[Note:</i> Requiring default constructibility of
<code>value_type</code> means that <code>ctr_</code> may first be
constructed with its required span size, and then filled by iterating
over all unique multidimensional indices <code>i...</code> in the
<code>mdarray</code>’s domain. Alternately, <code>ctr_</code> may be
constructed via <code>ranges::to</code>, if the elements of
<code>other</code> can be viewed by a range. The intent is to permit
<code>ranges::to</code> initialization of <code>ctr_</code> if possible,
without requiring a particular iteration order (as the best-performing
order can depend sensitively on the two layouts) or even requiring all
<code>mdspan</code> to be iterable by a range.<i>— end note]</i></p>
<p><span class="marginalizedparent"><a class="marginalized">41</a></span>
<em>Remarks:</em> The expression inside <code>explicit</code> is:</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="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="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">!</span>is_convertible_v<span class="op">&lt;</span>Accessor<span class="op">::</span>reference, value_type<span class="op">&gt;</span></span></code></pre></div>
<p><b>24.6.�.3 <code>mdarray</code> constructors with allocators
[mdarray.ctors.alloc]</b></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> Alloc<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> 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">1</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(1.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">(1.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">2</a></span>
<em>Preconditions:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.1)</a></span> Let
<code>map</code> be <code>mapping_type(ext)</code>, then</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.2)</a></span> if
<code>container_type</code> is a specialization of <code>array</code>,
<code>map.required_span_size() &lt;= size(container_type())</code> is
<code>true</code>, otherwise</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(2.3)</a></span>
<code>map.required_span_size() &lt;= size(container_type(map.required_span_size(), a))</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(3.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">(3.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="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> Alloc<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> mdarray<span class="op">(</span><span class="kw">const</span> mapping_type<span class="op">&amp;</span> map, <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">4</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">5</a></span>
<em>Preconditions:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.1)</a></span> if
<code>container_type</code> is a specialization of <code>array</code>,
<code>map.required_span_size() &lt;= size(container_type())</code> is
<code>true</code>, otherwise</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.2)</a></span>
<code>map.required_span_size() &lt;= size(container_type(map.required_span_size(), a))</code>
is <code>true</code>.</p></li>
</ul>
<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>map</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>map.required_span_size()</code> as the first argument and
<code>a</code> as the second argument.</p></li>
</ul>
<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">template</span><span class="op">&lt;</span><span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb46-2"><a href="#cb46-2" 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> value_type<span class="op">&amp;</span> val, <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">7</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(7.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">(7.2)</a></span> if
<code>container_type</code> is not a specialization of
<code>array</code>,
<code>is_constructible_v&lt;container_type, size_t, value_type, Alloc&gt;</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
<em>Preconditions:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(8.1)</a></span> Let
<code>map</code> be <code>mapping_type(ext)</code>, then</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(8.2)</a></span> if
<code>container_type</code> is a specialization of <code>array</code>,
<code>map.required_span_size() &lt;= size(container_type())</code> is
<code>true</code>, otherwise</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(8.3)</a></span>
<code>map.required_span_size() &lt;= size(container_type(map.required_span_size(), val, a))</code>
is <code>true</code>.</p></li>
</ul>
<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>ext</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(9.2)</a></span> if
<code>is_constructible_v&lt;container_type, size_t, value_type&gt;</code>
is <code>true</code>, direct-non-list-initializes <code>ctr_</code> with
<code>container_type(</code><em><code>map_</code></em><code>.required_span_size(), val)</code>,
otherwise direct-non-list-initializes <code>ctr_</code> with
<em><code>value-to-array</code></em><code>&lt;element_type, size(declval&lt;container_type&gt;())&gt;()</code>.</p></li>
</ul>
<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> Alloc<span class="op">&gt;</span></span>
<span id="cb47-2"><a href="#cb47-2" 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> map, <span class="kw">const</span> value_type<span class="op">&amp;</span> val, <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">10</a></span>
<em>Constraints:</em> if <code>container_type</code> is not a
specialization of <code>array</code>,
<code>is_constructible_v&lt;container_type, size_t, value_type&gt;</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">11</a></span>
<em>Preconditions:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(11.1)</a></span> if
<code>container_type</code> is a specialization of <code>array</code>,
<code>map.required_span_size() &lt;= size(container_type())</code> is
<code>true</code>, otherwise</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(11.2)</a></span>
<code>map.required_span_size() &lt;= size(container_type(map.required_span_size(), val, a))</code>
is <code>true</code>.</p></li>
</ul>
<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>map</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(12.2)</a></span> if
<code>is_constructible_v&lt;container_type, size_t, value_type&gt;</code>
is <code>true</code>, direct-non-list-initializes <code>ctr_</code> with
<code>container_type(</code><em><code>map_</code></em><code>.required_span_size(), val)</code>,
otherwise direct-non-list-initializes <code>ctr_</code> with
<em><code>value-to-array</code></em><code>&lt;element_type, size(declval&lt;container_type&gt;())&gt;()</code>.</p></li>
</ul>
<div class="sourceCode" id="cb48"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb48-1"><a href="#cb48-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="cb48-2"><a href="#cb48-2" 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> container_type<span class="op">&amp;</span> c, <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">13</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(13.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">(13.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">14</a></span>
<em>Preconditions:</em>
<code>c.size() &gt;= mapping_type(ext).required_span_size()</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">15</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(15.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">(15.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="cb49"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb49-1"><a href="#cb49-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="cb49-2"><a href="#cb49-2" 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> container_type<span class="op">&amp;</span> c, <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">16</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">17</a></span>
<em>Preconditions:</em>
<code>c.size() &gt;= m.required_span_size()</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">18</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(18.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">(18.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="cb50"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb50-1"><a href="#cb50-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="cb50-2"><a href="#cb50-2" 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, container_type<span class="op">&amp;&amp;</span> c, <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">19</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(19.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">(19.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">20</a></span>
<em>Preconditions:</em>
<code>c.size() &gt;= mapping_type(ext).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>ext</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(21.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="cb51"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb51-1"><a href="#cb51-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="cb51-2"><a href="#cb51-2" 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, container_type<span class="op">&amp;&amp;</span> c, <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">22</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">23</a></span>
<em>Preconditions:</em>
<code>c.size() &gt;= m.required_span_size()</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">24</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(24.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">(24.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="cb52"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb52-1"><a href="#cb52-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="cb52-2"><a href="#cb52-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="cb52-3"><a href="#cb52-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="cb52-4"><a href="#cb52-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="cb52-5"><a href="#cb52-5" aria-hidden="true" tabindex="-1"></a>                                  OtherLayoutPolicy, OtherContainer<span class="op">&gt;&amp;</span> other,</span>
<span id="cb52-6"><a href="#cb52-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">25</a></span>
<em>Mandates:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(25.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">(25.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">26</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(26.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">(26.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">27</a></span>
<em>Preconditions:</em> 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>.</p>
<p><span class="marginalizedparent"><a class="marginalized">28</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(28.1)</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">(28.2)</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">29</a></span>
<em>Remarks:</em> The expression inside <code>explicit</code> is:</p>
<div class="sourceCode" id="cb53"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb53-1"><a href="#cb53-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="cb53-2"><a href="#cb53-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="cb54"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb54-1"><a href="#cb54-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="cb54-2"><a href="#cb54-2" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> OtherLayoutPolicy, <span class="kw">class</span> Accessor,</span>
<span id="cb54-3"><a href="#cb54-3" aria-hidden="true" tabindex="-1"></a>           <span class="kw">class</span> Alloc<span class="op">&gt;</span></span>
<span id="cb54-4"><a href="#cb54-4" 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="cb54-5"><a href="#cb54-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdarray<span class="op">(</span><span class="kw">const</span> mdspan<span class="op">&lt;</span>OtherElementType, OtherExtents,</span>
<span id="cb54-6"><a href="#cb54-6" aria-hidden="true" tabindex="-1"></a>                                   OtherLayoutPolicy, Accessor<span class="op">&gt;&amp;</span> other,</span>
<span id="cb54-7"><a href="#cb54-7" 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">30</a></span>
<em>Mandates:</em>
<code>is_constructible_v&lt;extents_type, OtherExtents&gt;</code> is
<code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">31</a></span>
<em>Constraints:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(31.1)</a></span>
<code>is_constructible_v&lt;container_type, size_t, Alloc&gt;</code> is
<code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(31.2)</a></span>
<code>is_constructible_v&lt;value_type, Accessor::reference&gt;</code>
is <code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(31.3)</a></span>
<code>is_assignable_v&lt;Accessor::reference, value_type&gt;</code> is
<code>true</code>,</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(31.4)</a></span>
<code>is_default_constructible_v&lt;value_type&gt;</code> is
<code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(31.5)</a></span>
<code>is_constructible_v&lt;mapping_type, const OtherLayoutPolicy::template mapping&lt;OtherExtents&gt;&amp;&gt;</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">32</a></span>
<em>Preconditions:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(32.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>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(32.2)</a></span> if
<code>container_type</code> is a specialization of <code>array</code>,
then
<code>container_type().size() &gt;= other.mapping().required_span_size()</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">33</a></span>
<em>Effects:</em></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized">(33.1)</a></span>
Direct-non-list-initializes <em><code>map_</code></em> with
<code>extents_type(other.extents())</code>;</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(33.2)</a></span>
direct-non-list-initializes <code>ctr_</code> with
<code>container_type(</code><em><code>map_</code></em><code>.required_span_size(), a)</code>;
and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(33.3)</a></span> for
all unique multidimensional indices <code>i...</code> in
other.extents(), assigns <code>other[i...]</code> to
<code>ctr_[</code><em><code>map_</code></em><code>(i...)]</code>.</p></li>
</ul>
<p><i>[Note:</i> For intent, please see Note on the <code>mdarray</code>
constructor taking an <code>mdspan</code> with no allocator.<i>— end
note]</i></p>
<p><span class="marginalizedparent"><a class="marginalized">34</a></span>
<em>Remarks:</em> The expression inside <code>explicit</code> is:</p>
<div class="sourceCode" id="cb55"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb55-1"><a href="#cb55-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="cb55-2"><a href="#cb55-2" aria-hidden="true" tabindex="-1"></a>  <span class="op">!</span>is_convertible_v<span class="op">&lt;</span>Accessor<span class="op">::</span>reference, value_type<span class="op">&gt;</span> <span class="op">||</span></span>
<span id="cb55-3"><a href="#cb55-3" aria-hidden="true" tabindex="-1"></a>  <span class="op">!</span>is_convertible_v<span class="op">&lt;</span>Alloc, container_type<span class="op">::</span>allocator_type<span class="op">&gt;</span></span></code></pre></div>
<!--

  #              #                           #
### ### ###  ##     ##      ###  ## ### ###     ##  ###
# # # # ### # #  #  # #     ### # # # # # #  #  # # # #
### ### # # ###  ## # #     # # ### ### ###  ## # #  ##
                                    #   #           ###
-->
<p><br /> <b>24.6.�.4 <code>mdarray</code> members
[mdarray.members]</b></p>
<div class="sourceCode" id="cb56"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb56-1"><a href="#cb56-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> OtherIndexTypes<span class="op">&gt;</span></span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> reference <span class="kw">operator</span><span class="op">[](</span>OtherIndexTypes<span class="op">...</span> indices<span class="op">)</span>;</span>
<span id="cb56-3"><a href="#cb56-3" 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> OtherIndexTypes<span class="op">&gt;</span></span>
<span id="cb56-4"><a href="#cb56-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> const_reference <span class="kw">operator</span><span class="op">[](</span>OtherIndexTypes<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">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;OtherIndexTypes, index_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;index_type, OtherIndexTypes&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...(OtherIndexTypes) == 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>extents_type::</code><em><code>index-cast</code></em><code>(std::move(indices))</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">3</a></span>
<em>Preconditions:</em></p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized">(3.1)</a></span>
<code>I</code> is a multidimensional index in <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>;</li>
<li><span class="marginalizedparent"><a class="marginalized">(3.2)</a></span>
<code>container_size() &gt;=</code><em><code>map_</code></em><code>.required_span_size()</code>
is <code>true</code>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">4</a></span>
<em>Effects:</em> Equivalent to: <code>return</code>
<em><code>acc_</code></em><code>.access(</code><em><code>ptr_</code></em><code>,</code><em><code>map_</code></em><code>(static_cast&lt;index_type&gt;(std::move(indices))...));</code></p>
<div class="sourceCode" id="cb57"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherIndexType<span class="op">&gt;</span></span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> reference <span class="kw">operator</span><span class="op">[](</span>span<span class="op">&lt;</span>OtherIndexType, rank<span class="op">()&gt;</span> indices<span class="op">)</span>;</span>
<span id="cb57-3"><a href="#cb57-3" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherIndexType<span class="op">&gt;</span></span>
<span id="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> const_reference <span class="kw">operator</span><span class="op">[](</span>span<span class="op">&lt;</span>OtherIndexType, rank<span class="op">()&gt;</span> indices<span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb57-5"><a href="#cb57-5" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherIndexType<span class="op">&gt;</span></span>
<span id="cb57-6"><a href="#cb57-6" 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>OtherIndexType, rank<span class="op">()&gt;&amp;</span> indices<span class="op">)</span>;</span>
<span id="cb57-7"><a href="#cb57-7" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherIndexType<span class="op">&gt;</span></span>
<span id="cb57-8"><a href="#cb57-8" 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>OtherIndexType, rank<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">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;const OtherIndexType&amp;, index_type&gt;</code>
is <code>true</code>, and</p></li>
<li><p><span class="marginalizedparent"><a class="marginalized">(5.2)</a></span>
<code>is_nothrow_constructible_v&lt;index_type, const OtherIndexType&amp;&gt;</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">6</a></span>
<em>Effects:</em> Let <code>P</code> be a 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[](as_const(indices[P])...);</code></p>
<div class="sourceCode" id="cb58"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb58-1"><a href="#cb58-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 class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">7</a></span>
<em>Precondition:</em> The size of the multidimensional index space
<code>extents()</code> is a representable value of type
<code>size_type</code> ([basic.fundamental]).</p>
<p><span class="marginalizedparent"><a class="marginalized">8</a></span>
<em>Returns:</em>
<code>extents().</code><em><code>fwd-prod-of-extents</code></em><code>(rank())</code>.</p>
<div class="sourceCode" id="cb59"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a><span class="op">[[</span><span class="at">nodiscard</span><span class="op">]]</span> <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">9</a></span>
<em>Returns:</em> <code>true</code> if the size of the multidimensional
index space <code>extents()</code> is 0, otherwise
<code>false</code>.</p>
<div class="sourceCode" id="cb60"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a><span class="kw">friend</span> <span class="kw">constexpr</span> <span class="dt">void</span> swap<span class="op">(</span>mdarray<span class="op">&amp;</span> x, mdarray<span class="op">&amp;</span> y<span class="op">)</span> <span class="kw">noexcept</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">10</a></span>
<em>Effects:</em> Equivalent to:</p>
<div class="sourceCode" id="cb61"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a>swap<span class="op">(</span>x<span class="op">.</span>ctr_, y<span class="op">.</span>ctr_<span class="op">)</span>;</span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a>swap<span class="op">(</span>x<span class="op">.</span><em>map</em>_, y<span class="op">.</span><em>map</em>_<span class="op">)</span>;</span></code></pre></div>
<div class="sourceCode" id="cb62"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb62-1"><a href="#cb62-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="cb62-2"><a href="#cb62-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="cb62-3"><a href="#cb62-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">11</a></span>
<em>Constraints:</em></p>
<ul>
<li><p>[11.1]{pnum}
<code>is_assignable_v&lt;mdspan&lt;element_type, extents_type, layout_type&gt;, mdspan&lt;OtherElementType, OtherExtents, OtherLayoutType, OtherAccessorType&gt;&gt;</code>
is <code>true</code>.</p></li>
<li><p>[11.2]{pnum} <code>is_same_v&lt;pointer, element_type*&gt;</code>
is <code>true</code>.</p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized">12</a></span>
<em>Preconditions:</em>
<code>container_size() &gt;=</code><em><code>map_</code></em><code>.required_span_size()</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">13</a></span>
<em>Returns:</em>
<code>mdspan(container_data(),</code><em><code>map_</code></em>)`</p>
<div class="sourceCode" id="cb63"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb63-1"><a href="#cb63-1" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherAccessorType<span class="op">&gt;</span></span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdspan<span class="op">&lt;</span>element_type, extents_type, layout_type, OtherAccessorType<span class="op">&gt;</span></span>
<span id="cb63-3"><a href="#cb63-3" aria-hidden="true" tabindex="-1"></a>      to_mdspan<span class="op">(</span><span class="kw">const</span> OtherAccessorType<span class="op">&amp;</span> a <span class="op">=</span> default_accessor<span class="op">&lt;</span>element_type<span class="op">&gt;())</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">14</a></span>
<em>Constraints:</em>
<code>is_assignable_v&lt;pointer, typename OtherAccessorType::data_handle_type&gt;</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">15</a></span>
<em>Preconditions:</em>
<code>container_size() &gt;=</code><em><code>map_</code></em><code>.required_span_size()</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">16</a></span>
<em>Returns:</em>
<code>mdspan&lt;element_type, extents_type, layout_type, OtherAccessorType&gt;(container_data(),</code><em><code>map_</code></em><code>, a)</code></p>
<div class="sourceCode" id="cb64"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb64-1"><a href="#cb64-1" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> OtherAccessorType<span class="op">&gt;</span></span>
<span id="cb64-2"><a href="#cb64-2" aria-hidden="true" tabindex="-1"></a>    <span class="kw">constexpr</span> mdspan<span class="op">&lt;</span><span class="kw">const</span> element_type, extents_type, layout_type, OtherAccessorType<span class="op">&gt;</span></span>
<span id="cb64-3"><a href="#cb64-3" aria-hidden="true" tabindex="-1"></a>      to_mdspan<span class="op">(</span><span class="kw">const</span> OtherAccessorType<span class="op">&amp;</span> a <span class="op">=</span> default_accessor<span class="op">&lt;</span><span class="kw">const</span> element_type<span class="op">&gt;())</span> <span class="kw">const</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized">17</a></span>
<em>Constraints:</em>
<code>is_assignable_v&lt;const_pointer, typename OtherAccessorType::data_handle_type&gt;</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">18</a></span>
<em>Preconditions:</em>
<code>container_size() &gt;=</code><em><code>map_</code></em><code>.required_span_size()</code>
is <code>true</code>.</p>
<p><span class="marginalizedparent"><a class="marginalized">19</a></span>
<em>Returns:</em>
<code>mdspan&lt;const element_type, extents_type, layout_type, OtherAccessorType&gt;(container_data(),</code><em><code>map_</code></em><code>, a)</code></p>
<p><br /></p>
<p>Add to <code>mdspan</code> deduction guides</p>
<div class="sourceCode" id="cb65"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb65-1"><a href="#cb65-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> Layout, <span class="kw">class</span> Container<span class="op">&gt;</span></span>
<span id="cb65-2"><a href="#cb65-2" aria-hidden="true" tabindex="-1"></a>mdspan<span class="op">(</span>mdarray<span class="op">&lt;</span>ElementType, Extents, Layout, Container<span class="op">&gt;)</span> <span class="op">-&gt;</span> mdspan<span class="op">&lt;</span></span>
<span id="cb65-3"><a href="#cb65-3" aria-hidden="true" tabindex="-1"></a>  <span class="kw">decltype</span><span class="op">(</span>declval<span class="op">&lt;</span>mdarray<span class="op">&lt;</span>ElementType, Extents, Layout, Container<span class="op">&gt;&gt;().</span>to_mdspan<span class="op">())::</span>element_type,</span>
<span id="cb65-4"><a href="#cb65-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">decltype</span><span class="op">(</span>declval<span class="op">&lt;</span>mdarray<span class="op">&lt;</span>ElementType, Extents, Layout, Container<span class="op">&gt;&gt;().</span>to_mdspan<span class="op">())::</span>extens_type,</span>
<span id="cb65-5"><a href="#cb65-5" aria-hidden="true" tabindex="-1"></a>  <span class="kw">decltype</span><span class="op">(</span>declval<span class="op">&lt;</span>mdarray<span class="op">&lt;</span>ElementType, Extents, Layout, Container<span class="op">&gt;&gt;().</span>to_mdspan<span class="op">())::</span>layout_type,</span>
<span id="cb65-6"><a href="#cb65-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">decltype</span><span class="op">(</span>declval<span class="op">&lt;</span>mdarray<span class="op">&lt;</span>ElementType, Extents, Layout, Container<span class="op">&gt;&gt;().</span>to_mdspan<span class="op">())::</span>accessor_type<span class="op">&gt;</span>;</span></code></pre></div>
<h1 data-number="7" id="acknowledgements"><span class="header-section-number">7</span> Acknowledgements<a href="#acknowledgements" class="self-link"></a></h1>
<p>Sandia National Laboratories is a multimission laboratory managed and
operated by National Technology and Engineering Solutions of Sandia,
LLC., a wholly owned subsidiary of Honeywell International, Inc., for
the U.S. Department of Energy’s National Nuclear Security Administration
under contract DE-NA-0003525.</p>
<p>This work was supported by the Exascale Computing Project
(17-SC-20-SC), a collaborative effort of the U.S. Department of Energy
Office of Science and the National Nuclear Security Administration.</p>
<h1 data-number="8" id="references"><span class="header-section-number">8</span> References<a href="#references" class="self-link"></a></h1>
<div id="refs" class="references csl-bib-body" role="doc-bibliography">
<div id="ref-P1684R0" class="csl-entry" role="doc-biblioentry">
<div class="csl-left-margin">[P1684R0] </div><div class="csl-right-inline">David Hollman, Christian Trott, Mark Hoemmen,
Daniel Sundernland. 2019. mdarray: An Owning Multidimensional Array
Analog of mdspan. <a href="https://wg21.link/p1684r0"><div class="csl-block">https://wg21.link/p1684r0</div></a></div>
</div>
</div>
</div>
</div>
</body>
</html>
