<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
<title>P0009r3 : Polymorphic Multidimensional Array Reference</title>
<meta name="date" content="2016-10-14" />
<meta name="author" content="H. Carter Edwards" />
<meta name="author" content="Bryce Lelbach" />
<meta name="author" content="Christian Trott" />
<meta name="author" content="Mauro Bianco" />
<meta name="author" content="Robin Maffeo" />
<meta name="author" content="Ben Sander" />
<style type="text/css">

/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
  overflow: hidden;
}

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin: 0 0 0.5em 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left, .figure.align-left, object.align-left {
  clear: left ;
  float: left ;
  margin-right: 1em }

img.align-right, .figure.align-right, object.align-right {
  clear: right ;
  float: right ;
  margin-left: 1em }

img.align-center, .figure.align-center, object.align-center {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.align-left {
  text-align: left }

.align-center {
  clear: both ;
  text-align: center }

.align-right {
  text-align: right }

/* reset inner alignment in figures */
div.align-right {
  text-align: inherit }

/* div.align-center * { */
/*   text-align: left } */

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font: inherit }

pre.literal-block, pre.doctest-block, pre.math, pre.code {
  margin-left: 2em ;
  margin-right: 2em }

pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
  border: 0px;
  border-top: 2px solid;
  border-bottom: 2px solid;
  border-collapse: collapse;
}
table.docutils.booktabs * {
  border: 0px;
}
table.docutils.booktabs th {
  border-bottom: thin solid;
  text-align: left;
}

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="p0009r3-polymorphic-multidimensional-array-reference">
<h1 class="title">P0009r3 : Polymorphic Multidimensional Array Reference</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">Project:</th><td class="field-body">ISO JTC1/SC22/WG21: Programming Language C++</td>
</tr>
<tr class="field"><th class="docinfo-name">Number:</th><td class="field-body">P0009r3</td>
</tr>
<tr><th class="docinfo-name">Date:</th>
<td>2016-10-14</td></tr>
<tr class="field"><th class="docinfo-name">Reply-to:</th><td class="field-body"><a class="reference external" href="mailto:hcedwar&#64;sandia.gov">hcedwar&#64;sandia.gov</a>, <a class="reference external" href="mailto:balelbach&#64;lbl.gov">balelbach&#64;lbl.gov</a></td>
</tr>
<tr><th class="docinfo-name">Author:</th>
<td>H. Carter Edwards</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:hcedwar&#64;sandia.gov">hcedwar&#64;sandia.gov</a></td></tr>
<tr><th class="docinfo-name">Author:</th>
<td>Bryce Lelbach</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:balelbach&#64;lbl.gov">balelbach&#64;lbl.gov</a></td></tr>
<tr><th class="docinfo-name">Author:</th>
<td>Christian Trott</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:crtrott&#64;sandia.gov">crtrott&#64;sandia.gov</a></td></tr>
<tr><th class="docinfo-name">Author:</th>
<td>Mauro Bianco</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:mbianco&#64;cscs.ch">mbianco&#64;cscs.ch</a></td></tr>
<tr><th class="docinfo-name">Author:</th>
<td>Robin Maffeo</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:Robin.Maffeo&#64;amd.com">Robin.Maffeo&#64;amd.com</a></td></tr>
<tr><th class="docinfo-name">Author:</th>
<td>Ben Sander</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:ben.sander&#64;amd.com">ben.sander&#64;amd.com</a></td></tr>
<tr class="field"><th class="docinfo-name">Audience:</th><td class="field-body">Library Evolution Working Group (LEWG)</td>
</tr>
<tr class="field"><th class="docinfo-name">URL:</th><td class="field-body"><a class="reference external" href="https://github.com/kokkos/array_ref/blob/master/proposals/P0009.rst">https://github.com/kokkos/array_ref/blob/master/proposals/P0009.rst</a></td>
</tr>
</tbody>
</table>
<div class="section" id="description">
<h1>1&nbsp;&nbsp;&nbsp;Description</h1>
<p>The proposed polymorphic multidimensional array reference (<tt class="docutils literal">array_ref</tt>)
defines types and functions for mapping indices from a
multidimensional index space (the domain)
to members of a contiguous span of objects (the codomain).
This <strong>layout mapping</strong> is one <em>property</em> of the
<tt class="docutils literal">array_ref</tt> that may be specified through a template parameter.
The intent is that <em>properties*</em> are an extensible set of options
for multi-index mapping and member access.
For example,
bounds checking the input multi-index versus the multdimensional extents or
accessing members through an atomic interface.
The recent Accessors paper (P0367) introduces a rich set of potential access properties.</p>
<div class="section" id="multidimensional-array-not-array-of-array-of-array-of-array">
<h2>1.1&nbsp;&nbsp;&nbsp;Multidimensional array, not array-of-array-of-array-of-array...</h2>
<p>The multidimensional array abstraction has been fundamental
to numerical computations for over five decades.
However, the C/C++ language provides only a one dimensional array
abstraction which can be composed into array-of-array-of-array... types.
While such types have some similarity to multidimensional arrays they
do not provide adequate multidimensional array functionality
of this proposal.
Two critical functionality differences are
(1) multiple dynamic extents and
(2) polymorphic mapping of multi-indices to member objects.</p>
</div>
<div class="section" id="relationship-to-p0454-wording-for-a-minimal-mdspan">
<h2>1.2&nbsp;&nbsp;&nbsp;Relationship to P0454 : Wording for a Minimal <tt class="docutils literal">mdspan</tt></h2>
<p>P0454, Wording for a Minimal <tt class="docutils literal">mdspan</tt>, includes a minimal version of the
polymorphic multidimensional array reference capability that aligns with
<tt class="docutils literal">span</tt> as proposed in P0122.</p>
<p>Assuming acceptance of P0454 our intent is for a subsequent version of
this paper to propose extensions to <tt class="docutils literal">mdspan</tt> for layout extensibility
and other essential properties.</p>
<p>Note that the <tt class="docutils literal">array_ref</tt> name in this paper is not entirely satisfactory
and the following alternatives were brainstormed during prior LEWG reviews.</p>
<table border="1" class="docutils">
<colgroup>
<col width="38%" />
<col width="63%" />
</colgroup>
<tbody valign="top">
<tr><td>LEWG
2015-10-22</td>
<td>LEWG
2016-06-25</td>
</tr>
<tr><td>view ,
span ,
array_ref ,
slice ,
array_view ,
ref ,
array_span ,
basic_span ,
object_span ,
field</td>
<td>sci_span ,
numeric_span ,
multidimensional_span ,
multidim_span ,
md_span ,
vla_span ,
multispan ,
multi_span</td>
</tr>
</tbody>
</table>
<p>When P0454 is accepted the name will become <tt class="docutils literal">mdspan</tt>.</p>
</div>
<div class="section" id="alternative-mechanisms-for-specifying-the-domain-multi-index-space">
<h2>1.3&nbsp;&nbsp;&nbsp;Alternative mechanisms for specifying the domain multi-index space</h2>
<p>Two potential mechanisms for specifying the domain multi-index space are possible.</p>
<p><strong>(A)</strong> The <strong>preferred mechanism</strong> is concise and aligns with
language syntax for specifying multidimensional array extents.
However, the preferred mechanism requires a trivial language change to relax
the specification for <em>incomplete</em> array types to support
multiple dynamic extents.
This trivial language change is proposed in P0332.</p>
<pre class="code c++ literal-block">
<span class="keyword">using</span> <span class="name">A_type</span> <span class="operator">=</span> <span class="name">std</span><span class="operator">::</span><span class="name">array_ref</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][</span><span class="literal number integer">8</span><span class="punctuation">][</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">&gt;</span> <span class="punctuation">;</span>

<span class="comment single">// standard array traits extracted from data type
</span>
<span class="keyword">static_assert</span><span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">rank</span><span class="operator">&lt;</span>   <span class="keyword type">int</span><span class="punctuation">[][</span><span class="literal number integer">8</span><span class="punctuation">][</span><span class="literal number integer">3</span><span class="punctuation">]</span>     <span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">==</span> <span class="literal number integer">3</span> <span class="punctuation">);</span>
<span class="keyword">static_assert</span><span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">extent</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][</span><span class="literal number integer">8</span><span class="punctuation">][</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="punctuation">,</span> <span class="literal number integer">0</span> <span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">==</span> <span class="literal number integer">0</span> <span class="punctuation">);</span>
<span class="keyword">static_assert</span><span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">extent</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][</span><span class="literal number integer">8</span><span class="punctuation">][</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="punctuation">,</span> <span class="literal number integer">1</span> <span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">==</span> <span class="literal number integer">8</span> <span class="punctuation">);</span>
<span class="keyword">static_assert</span><span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">extent</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][</span><span class="literal number integer">8</span><span class="punctuation">][</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="punctuation">,</span> <span class="literal number integer">2</span> <span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">==</span> <span class="literal number integer">3</span> <span class="punctuation">);</span>
</pre>
<!--  -->
<p><strong>(B)</strong> The <strong>undesirable mechanism</strong> requires an additional <tt class="docutils literal">extents</tt>
and <tt class="docutils literal">dyn</tt> property symbols.
This mechanism is more verbose and requires the introduction of a
<em>magic</em> integral value to denote a dynamic extent.</p>
<pre class="code c++ literal-block">
<span class="comment single">// array traits given through new array traits types
</span>
<span class="keyword">using</span> <span class="name">A_type</span> <span class="name">std</span><span class="operator">::</span><span class="name">array_ref</span><span class="operator">&lt;</span> <span class="keyword type">int</span> <span class="punctuation">,</span> <span class="name">std</span><span class="operator">::</span><span class="name">extents</span><span class="operator">&lt;</span><span class="name">std</span><span class="operator">::</span><span class="name">dyn</span><span class="punctuation">,</span><span class="literal number integer">8</span><span class="punctuation">,</span><span class="literal number integer">3</span><span class="operator">&gt;</span> <span class="operator">&gt;</span> <span class="punctuation">;</span>
</pre>
<!--  -->
<p><strong>Common Result</strong></p>
<p>The <tt class="docutils literal">array_ref</tt> type resulting from either specification mechanism
has the same interface.</p>
<pre class="code c++ literal-block">
<span class="keyword type">int</span> <span class="operator">*</span> <span class="name">buffer</span> <span class="operator">=</span> <span class="comment multiline">/* buffer to span of integers */</span> <span class="punctuation">;</span>

<span class="name">A_type</span> <span class="name function">A</span><span class="punctuation">(</span> <span class="name">buffer</span> <span class="punctuation">,</span> <span class="name">N</span> <span class="punctuation">);</span>

<span class="comment single">// static rank and extents
</span>
<span class="keyword">static_assert</span><span class="punctuation">(</span> <span class="name">A_type</span><span class="operator">::</span><span class="name">rank</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">3</span> <span class="punctuation">);</span>
<span class="keyword">static_assert</span><span class="punctuation">(</span> <span class="name">A_type</span><span class="operator">::</span><span class="name">static_extent</span><span class="punctuation">(</span><span class="literal number integer">0</span><span class="punctuation">)</span> <span class="operator">=</span> <span class="literal number integer">0</span> <span class="punctuation">);</span>
<span class="keyword">static_assert</span><span class="punctuation">(</span> <span class="name">A_type</span><span class="operator">::</span><span class="name">static_extent</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">)</span> <span class="operator">=</span> <span class="literal number integer">8</span> <span class="punctuation">);</span>
<span class="keyword">static_assert</span><span class="punctuation">(</span> <span class="name">A_type</span><span class="operator">::</span><span class="name">static_extent</span><span class="punctuation">(</span><span class="literal number integer">2</span><span class="punctuation">)</span> <span class="operator">=</span> <span class="literal number integer">3</span> <span class="punctuation">);</span>

<span class="comment single">// runtime extents
</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">A</span><span class="punctuation">.</span><span class="name">extent</span><span class="punctuation">(</span><span class="literal number integer">0</span><span class="punctuation">)</span> <span class="operator">=</span> <span class="name">N</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">A</span><span class="punctuation">.</span><span class="name">extent</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">)</span> <span class="operator">=</span> <span class="literal number integer">8</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">A</span><span class="punctuation">.</span><span class="name">extent</span><span class="punctuation">(</span><span class="literal number integer">2</span><span class="punctuation">)</span> <span class="operator">=</span> <span class="literal number integer">3</span> <span class="punctuation">);</span>

<span class="comment single">// member access through operator()
</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="operator">&amp;</span> <span class="name">A</span><span class="punctuation">(</span><span class="literal number integer">0</span><span class="punctuation">,</span><span class="literal number integer">0</span><span class="punctuation">,</span><span class="literal number integer">0</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="name">buffer</span> <span class="punctuation">);</span>
</pre>
<!--  -->
</div>
</div>
<div class="section" id="multidimensional-array-and-subarray">
<h1>2&nbsp;&nbsp;&nbsp;Multidimensional Array and Subarray</h1>
<div class="section" id="header-array-ref-synopsis-array-ref-and-subarray">
<h2>2.1&nbsp;&nbsp;&nbsp;Header <tt class="docutils literal">&lt;array_ref&gt;</tt> synopsis: <tt class="docutils literal">array_ref</tt> and <tt class="docutils literal">subarray</tt></h2>
<pre class="code c++ literal-block">
<span class="keyword">namespace</span> <span class="name">std</span> <span class="punctuation">{</span>
<span class="keyword">namespace</span> <span class="name">experimental</span> <span class="punctuation">{</span>

  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">DataType</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="punctuation">...</span> <span class="name">Properties</span> <span class="operator">&gt;</span>
  <span class="keyword">class</span> <span class="name class">array_ref</span> <span class="punctuation">;</span>

  <span class="comment single">// return type of subarray free function is an array_ref
</span>  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">DataType</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="punctuation">...</span> <span class="name">Properties</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="punctuation">...</span> <span class="name">SliceSpecifiers</span> <span class="operator">&gt;</span>
    <span class="comment single">// for exposition only:
</span>    <span class="name">detail</span><span class="operator">::</span><span class="keyword type">subarray_deduction_t</span><span class="operator">&lt;</span> <span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">DataType</span><span class="punctuation">,</span><span class="name">Properties</span><span class="punctuation">...</span><span class="operator">&gt;</span><span class="punctuation">,</span><span class="name">SliceSpecifiers</span><span class="punctuation">...</span><span class="operator">&gt;</span>
  <span class="name">subarray</span><span class="punctuation">(</span> <span class="name">array_ref</span><span class="operator">&lt;</span> <span class="name">DataType</span><span class="punctuation">,</span> <span class="name">Properties</span> <span class="punctuation">...</span> <span class="operator">&gt;</span> <span class="keyword">const</span> <span class="operator">&amp;</span> <span class="punctuation">,</span> <span class="name">SliceSpecifiers</span> <span class="punctuation">...</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="comment single">// tag supporting subarray
</span>  <span class="keyword">struct</span> <span class="name">all_type</span> <span class="punctuation">{};</span>
  <span class="keyword reserved">inline</span> <span class="keyword">constexpr</span> <span class="name">all_type</span> <span class="name">all</span> <span class="operator">=</span> <span class="name">all_type</span><span class="punctuation">{};</span>
<span class="punctuation">}}</span>
</pre>
<!--  -->
<p>The <tt class="docutils literal">array_ref</tt> class maps a multi-index within a multi-index space (the domain) to
a reference to an object within a span of objects (the codomain).</p>
<p>The <tt class="docutils literal">subarray</tt> free function generates an <tt class="docutils literal">array_ref</tt> with a domain contained
within the input <tt class="docutils literal">array_ref</tt> domain and codomain contained within the input
<tt class="docutils literal">array_ref</tt> codomain.</p>
<p>The alias <tt class="docutils literal"><span class="pre">detail::subarray_deduction_t</span></tt> class is not proposed and only appears for exposition.
An implementation metafunction of this form is necessary to deduce the specific
<tt class="docutils literal">array_ref</tt> return type of the <tt class="docutils literal">subarray</tt> function.</p>
</div>
<div class="section" id="template-class-array-ref">
<h2>2.2&nbsp;&nbsp;&nbsp;template class <tt class="docutils literal">array_ref</tt></h2>
<pre class="code c++ literal-block">
<span class="keyword">namespace</span> <span class="name">std</span> <span class="punctuation">{</span>
<span class="keyword">namespace</span> <span class="name">experimental</span> <span class="punctuation">{</span>

<span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span> <span class="name">DataType</span><span class="punctuation">,</span> <span class="keyword">typename</span><span class="punctuation">...</span> <span class="name">Properties</span><span class="operator">&gt;</span>
<span class="keyword">class</span> <span class="name class">array_ref</span> <span class="punctuation">{</span>
<span class="keyword">public</span><span class="operator">:</span>
  <span class="comment single">// domain and codomain types
</span>
  <span class="keyword">using</span> <span class="name">value_type</span> <span class="operator">=</span> <span class="keyword">typename</span> <span class="name">remove_all_extents</span><span class="operator">&lt;</span><span class="name">DataType</span><span class="operator">&gt;::</span><span class="name">type</span> <span class="punctuation">;</span>
  <span class="keyword">using</span> <span class="name">pointer</span>    <span class="operator">=</span> <span class="name">value_type</span> <span class="operator">*</span> <span class="punctuation">;</span>
  <span class="keyword">using</span> <span class="name">reference</span>  <span class="operator">=</span> <span class="comment multiline">/* implementation deduces from value_type and Properties... */</span> <span class="punctuation">;</span>
  <span class="keyword">using</span> <span class="name">size_type</span>  <span class="operator">=</span> <span class="comment multiline">/* implementation deduces from Properties... */</span> <span class="punctuation">;</span>
  <span class="keyword">using</span> <span class="name">layout</span>     <span class="operator">=</span> <span class="comment multiline">/* implementation deduces from Properties... */</span> <span class="punctuation">;</span>

  <span class="comment single">// Standard constructors, assignments, and destructor
</span>
  <span class="operator">~</span><span class="name">array_ref</span><span class="punctuation">()</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>

  <span class="keyword">constexpr</span> <span class="name">array_ref</span><span class="punctuation">()</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>
  <span class="keyword">constexpr</span> <span class="name">array_ref</span><span class="punctuation">(</span><span class="name">array_ref</span><span class="operator">&amp;&amp;</span><span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>
  <span class="keyword">constexpr</span> <span class="name">array_ref</span><span class="punctuation">(</span><span class="name">array_ref</span> <span class="keyword">const</span><span class="operator">&amp;</span><span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>
  <span class="name">array_ref</span><span class="operator">&amp;</span> <span class="keyword">operator</span><span class="operator">=</span><span class="punctuation">(</span><span class="name">array_ref</span><span class="operator">&amp;&amp;</span><span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>
  <span class="name">array_ref</span><span class="operator">&amp;</span> <span class="keyword">operator</span><span class="operator">=</span><span class="punctuation">(</span><span class="name">array_ref</span> <span class="keyword">const</span><span class="operator">&amp;</span><span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>

  <span class="comment single">// Constructor and assignment for assignables
</span>
  <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span> <span class="name">UType</span><span class="punctuation">,</span> <span class="keyword">typename</span> <span class="punctuation">...</span> <span class="name">UProp</span><span class="operator">&gt;</span>
  <span class="keyword">constexpr</span> <span class="name">array_ref</span><span class="punctuation">(</span> <span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">UType</span><span class="punctuation">,</span> <span class="name">UProp</span><span class="punctuation">...</span><span class="operator">&gt;</span> <span class="keyword">const</span><span class="operator">&amp;</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span> <span class="name">UType</span><span class="punctuation">,</span> <span class="keyword">typename</span> <span class="punctuation">...</span> <span class="name">UProp</span><span class="operator">&gt;</span>
  <span class="name">array_ref</span><span class="operator">&amp;</span> <span class="keyword">operator</span><span class="operator">=</span><span class="punctuation">(</span> <span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">UType</span><span class="punctuation">,</span> <span class="name">UProp</span><span class="punctuation">...</span><span class="operator">&gt;</span> <span class="keyword">const</span><span class="operator">&amp;</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="comment single">// Wrapping constructors
</span>
  <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span><span class="punctuation">...</span> <span class="name">IntegralExtent</span><span class="operator">&gt;</span>
  <span class="keyword">explicit</span> <span class="keyword">constexpr</span> <span class="name">array_ref</span><span class="punctuation">(</span><span class="name">pointer</span><span class="punctuation">,</span> <span class="name">IntegralExtent</span><span class="punctuation">...</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="keyword">explicit</span> <span class="keyword">constexpr</span> <span class="name">array_ref</span><span class="punctuation">(</span><span class="name">pointer</span><span class="punctuation">,</span> <span class="name">layout</span> <span class="keyword">const</span><span class="operator">&amp;</span><span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="comment single">// mapping domain multi-index to access codomain member
</span>
  <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span><span class="punctuation">...</span> <span class="name">IntegralIndex</span><span class="operator">&gt;</span>
  <span class="name">reference</span> <span class="keyword">operator</span><span class="punctuation">()(</span><span class="name">IntegralIndex</span><span class="punctuation">...)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span> <span class="name">IntegralIndex</span><span class="operator">&gt;</span>
  <span class="name">reference</span> <span class="keyword">operator</span><span class="punctuation">[](</span> <span class="name">IntegralIndex</span> <span class="punctuation">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span> <span class="comment single">// requires rank() == 1
</span>
  <span class="comment single">// observers of domain: [0..extent(0))X[0..extent(1))X...X[0..extent(rank()-1))
</span>
  <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">int</span> <span class="name">rank</span><span class="punctuation">()</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>
  <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">int</span> <span class="name">rank_dynamic</span><span class="punctuation">()</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">static_extent</span><span class="punctuation">(</span><span class="keyword type">int</span><span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">extent</span><span class="punctuation">(</span><span class="keyword type">int</span><span class="punctuation">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">size</span><span class="punctuation">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="comment single">// observers of the codomain: [data()..data()+span())
</span>
  <span class="keyword">constexpr</span> <span class="name">pointer</span> <span class="name">data</span><span class="punctuation">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">span</span><span class="punctuation">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span><span class="punctuation">...</span> <span class="name">IntegralExtent</span><span class="operator">&gt;</span>
  <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">required_span</span><span class="punctuation">(</span> <span class="name">IntegralExtent</span> <span class="punctuation">...</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">required_span</span><span class="punctuation">(</span> <span class="name">layout</span> <span class="keyword">const</span> <span class="operator">&amp;</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="comment single">// observers of the mapping : domain -&gt; codomain
</span>
  <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_always_unique</span>     <span class="operator">=</span> <span class="comment multiline">/* deduced */</span> <span class="punctuation">;</span>
  <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_always_contiguous</span> <span class="operator">=</span> <span class="comment multiline">/* deduced */</span> <span class="punctuation">;</span>
  <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_always_strided</span>    <span class="operator">=</span> <span class="comment multiline">/* deduced */</span> <span class="punctuation">;</span>

  <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_unique</span><span class="punctuation">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>
  <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_contiguous</span><span class="punctuation">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>
  <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_strided</span><span class="punctuation">()</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">stride</span><span class="punctuation">(</span><span class="keyword type">int</span><span class="punctuation">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>
<span class="punctuation">};</span>

<span class="punctuation">}}</span>
</pre>
<!--  -->
<div class="section" id="template-arguments">
<h3>2.2.1&nbsp;&nbsp;&nbsp;Template arguments</h3>
<p><tt class="docutils literal">template &lt;typename DataType, <span class="pre">typename...</span> Properties&gt; class array_ref</tt></p>
<p><strong>(A) Preferred Extent Specification Mechanism</strong></p>
<p><tt class="docutils literal">DataType</tt></p>
<blockquote>
<p>Requires: Is a complete or incomplete array type (8.3.4.p3).
Each omitted static extent in the incomplete array type, <tt class="docutils literal">[]</tt>,
denotes a <em>dynamic</em> extent.</p>
<p>Effects:  The value type, domain index space rank, static extents, and identification of
dynamic extents is determined from the possibly incomplete array type <tt class="docutils literal">DataType</tt> .</p>
<div class="line-block">
<div class="line"><tt class="docutils literal">value_type</tt> is <tt class="docutils literal"><span class="pre">std::remove_all_extents&lt;DataType&gt;::type</span> ;</tt></div>
<div class="line"><tt class="docutils literal">rank()</tt> is <tt class="docutils literal"><span class="pre">std::rank&lt;DataType&gt;::value</span></tt></div>
<div class="line"><tt class="docutils literal">static_extent(i)</tt> is <tt class="docutils literal"><span class="pre">std::extent&lt;DataType,i&gt;::value</span></tt></div>
<div class="line">A dynamic extent is indicated when <tt class="docutils literal"><span class="pre">std::extent&lt;DataType,i&gt;::value</span> == 0</tt></div>
</div>
</blockquote>
<p><tt class="docutils literal"><span class="pre">Properties...</span></tt></p>
<blockquote>
<p>Requires: <tt class="docutils literal">is_array_property_v&lt; Properties &gt;</tt> for each member of the pack.</p>
<p>Effects: The domain to codomain reference mapping is determined by the
content of the property pack.</p>
</blockquote>
<p><strong>(B) Undesirable Extent Specification Mechanism</strong></p>
<p><tt class="docutils literal">DataType</tt></p>
<blockquote>
Requires: Is a non-array type denoting the value type of the array.</blockquote>
<p><tt class="docutils literal"><span class="pre">Properties...</span></tt></p>
<blockquote>
<p>Requires: <tt class="docutils literal">is_array_property_v&lt; Properties &gt;</tt> for each member of the pack.</p>
<p>Effects:  The domain index space rank, static extents, and identification of
dynamic extents is determined from the <tt class="docutils literal">extents</tt> member of the property pack.
The domain to codomain mapping is determined by the remaining members of the property pack</p>
</blockquote>
</div>
<div class="section" id="fundamental-types">
<h3>2.2.2&nbsp;&nbsp;&nbsp;Fundamental Types</h3>
<p><tt class="docutils literal">using size_type = /* implementation defined */ ;</tt></p>
<blockquote>
Return type for extents and storage type for dynamic extents.</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">using value_type = typename <span class="pre">remove_all_extents&lt;DataType::type</span> ;</tt></div>
<div class="line"><tt class="docutils literal">using pointer = value_type * ;</tt></div>
</div>
<blockquote>
Type of the codomain member objects referenced by the array.</blockquote>
<p><tt class="docutils literal">using reference = /* deduced from DataType and <span class="pre">Properties...</span> */ ;</tt></p>
<blockquote>
Reference type for member access.
Unless modified to support special access properties
this is <tt class="docutils literal">value_type &amp;</tt>.
Special access properties may cause <tt class="docutils literal">reference</tt> to be a proxy type.</blockquote>
</div>
<div class="section" id="mapping-domain-multi-index-to-access-members-in-the-codomain">
<h3>2.2.3&nbsp;&nbsp;&nbsp;Mapping domain multi-index to access members in the codomain</h3>
<div class="line-block">
<div class="line"><tt class="docutils literal">template&lt; typename ... IntegralIndex &gt;</tt></div>
<div class="line"><tt class="docutils literal">reference <span class="pre">operator()(</span> IntegralIndex ... indices ) const noexcept</tt></div>
</div>
<blockquote>
<p>Requires: <tt class="docutils literal">indices</tt> is a multi-index in the domain:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">conjunction&lt;is_integral&lt;IntegralIndex&gt;::value...&gt;::value</span></tt></li>
<li><tt class="docutils literal">rank() &lt;= <span class="pre">sizeof...(IntegralIndex)</span></tt></li>
<li>The ith coordinate of <tt class="docutils literal"><span class="pre">indices...</span></tt>, denoted as <tt class="docutils literal">indices[ith]</tt>,
is in the domain: <tt class="docutils literal">0 &lt;= indices[ith] &lt; extent(ith)</tt>.</li>
<li>[Note: Because <tt class="docutils literal">extent(ith) == 1</tt> for <tt class="docutils literal">rank() &lt;= ith</tt>
then extra zero-value indices are valid. --end note]</li>
</ul>
<p>Returns: A <tt class="docutils literal">reference</tt> to the member object mapped to by <tt class="docutils literal"><span class="pre">indices...</span></tt>.</p>
<p>Remark: Optimization of the mapping operator is a critical
feature of the multidimensional array implementation.
Recommended optimizations include:</p>
<ul class="simple">
<li>Rank-specific overloads to better
enable optimization of the member access operator.</li>
<li>Inlining of a <tt class="docutils literal">constexpr</tt> multi-index mapping expression
that is <strong>not</strong> included in an optimizer's inlining budget.</li>
<li>Compile-time evaluation statically determined portions of
multi-index mapping expression.</li>
<li>Defering promotion of an <tt class="docutils literal">IntegralIndex</tt> until evaluation
of the multi-index mapping expression.</li>
</ul>
</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">template&lt; typename IntegralIndex &gt;</tt></div>
<div class="line"><tt class="docutils literal">reference <span class="pre">operator[](</span> IntegralIndex index ) const noexcept</tt></div>
</div>
<blockquote>
<p>Requires: <tt class="docutils literal"><span class="pre">is_integral&lt;IntegralIndex&gt;::value</span></tt>.
<tt class="docutils literal">rank() == 1</tt>.
<tt class="docutils literal">0 &lt;= i &lt; extent(0)</tt>.</p>
<p>Returns: A reference to the member object referenced by <tt class="docutils literal">index</tt>.</p>
<p>Requires: <tt class="docutils literal">0 &lt;= index &lt; extent(0)</tt></p>
</blockquote>
</div>
<div class="section" id="domain">
<h3>2.2.4&nbsp;&nbsp;&nbsp;Domain</h3>
<div class="line-block">
<div class="line"><tt class="docutils literal">static constexpr int rank() noexcept ;</tt></div>
<div class="line"><tt class="docutils literal">constexpr size_type extent(int r) const noexcept ;</tt></div>
</div>
<blockquote>
<p>Requires: <tt class="docutils literal">0 &lt;= r</tt></p>
<p>Returns: Rank and extents of the domain where the domain is
is the Cartesian product of the extents:
<tt class="docutils literal"><span class="pre">[0..extent(0))</span> X <span class="pre">[0..extent(1))</span> X ... X <span class="pre">[0..extent(rank()-1))</span></tt>.
If <tt class="docutils literal">rank() &lt;= r</tt> then <tt class="docutils literal">extent(r) == 1</tt>.</p>
</blockquote>
<p><tt class="docutils literal">static constexpr size_type static_extent(int r) const noexcept ;</tt></p>
<blockquote>
<p>Requires: <tt class="docutils literal">0 &lt;= r</tt></p>
<p>Returns: If <tt class="docutils literal">0 &lt;= r &lt; rank()</tt> the statically declared extent.
A statically declared extent of 0 denotes that the extent is dynamic.
If <tt class="docutils literal">rank() &lt;= r</tt> then <tt class="docutils literal">static_extent(r) == 1</tt>.</p>
</blockquote>
<p><tt class="docutils literal">constexpr size_type size() const noexcept ;</tt></p>
<blockquote>
Returns: product of extents.</blockquote>
<p><tt class="docutils literal">static constexpr int rank_dynamic() noexcept ;</tt></p>
<blockquote>
Returns: number of extents that are dynamic.</blockquote>
</div>
<div class="section" id="codomain">
<h3>2.2.5&nbsp;&nbsp;&nbsp;Codomain</h3>
<p>Not all members of the codomain may be accessible through the layout mapping;
i.e., the range of the mapping is contained within the codomain but may not
be equal to the codomain.</p>
<div class="line-block">
<div class="line"><tt class="docutils literal">constexpr pointer data() const noexcept ;</tt></div>
<div class="line"><tt class="docutils literal">constexpr size_type span() const noexcept ;</tt></div>
</div>
<blockquote>
Returns: The codomain is <tt class="docutils literal">[ data() .. data() + span() )</tt></blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">template&lt; typename ... IntegralExtent &gt;</tt></div>
<div class="line"><tt class="docutils literal">static constexpr size_type required_span( IntegralExtent ... dynamic_extent ) noexcept</tt></div>
<div class="line"><tt class="docutils literal">static constexpr size_type required_span( layout const &amp; ) noexcept</tt></div>
</div>
<blockquote>
<p>Requires: <tt class="docutils literal"><span class="pre">conjunction&lt;is_integral&lt;IntegralExtent&gt;::value...&gt;::value</span></tt>.
Each <tt class="docutils literal">dynamic_extent</tt> is non-negative.</p>
<p>Returns: Required length of contiguous span of objects
input the <em>wrapping constructor</em> with the corresponding extent argument.</p>
</blockquote>
</div>
<div class="section" id="mapping-domain-codomain">
<h3>2.2.6&nbsp;&nbsp;&nbsp;Mapping : domain -&gt; codomain</h3>
<p><tt class="docutils literal">using layout = /* deduced from <span class="pre">Properties...</span> */ ;</tt></p>
<blockquote>
Identification of the layout mapping.
If <tt class="docutils literal"><span class="pre">Properties...</span></tt> does not include a layout property then
<tt class="docutils literal">layout</tt> is <tt class="docutils literal">layout_right</tt> denoting the traditional C/C++ mapping.</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">static constexpr bool is_always_unique =</tt></div>
<div class="line"><tt class="docutils literal">constexpr bool is_unique() const noexcept ;</tt></div>
</div>
<blockquote>
A layout mapping is <em>unique</em> if each multi-index in the domain
is mapped to a unique member in the codomain.</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">static constexpr bool is_always_contiguous =</tt></div>
<div class="line"><tt class="docutils literal">constexpr bool is_contiguous() const noexcept ;</tt></div>
</div>
<blockquote>
<p>A layout mapping is <em>contiguous</em> if the layout mapping
can access every member of the codomain.</p>
<p>A layout mapping that is both unique and contiguous is <em>bijective</em>
and has <tt class="docutils literal">size() == span()</tt>.</p>
</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">static constexpr bool is_always_strided =</tt></div>
<div class="line"><tt class="docutils literal">constexpr bool is_strided() const noexcept ;</tt></div>
</div>
<blockquote>
A <em>strided</em> layout has constant striding between multi-index coordinates.
Let <tt class="docutils literal">A</tt> be an <tt class="docutils literal">array_ref</tt> and <tt class="docutils literal"><span class="pre">indices_V...</span></tt> and <tt class="docutils literal"><span class="pre">indices_U...</span></tt> be multi-indices
in the domain space such that all coordinates are equal except for
the <em>ith</em> coordinate where <tt class="docutils literal">indices_V[ith] = indices_U[ith] + 1</tt>.
Then <tt class="docutils literal">stride(ith) = distance(&amp; <span class="pre">A(indices_V...)</span> - &amp; A( <span class="pre">indices_U...</span> )</tt>
is constant for all coordinates.</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">template&lt; typename IntegralType &gt;</tt></div>
<div class="line"><tt class="docutils literal">constexpr size_type stride( IntegralType index ) const noexcept</tt></div>
</div>
<blockquote>
<p>Requires: <tt class="docutils literal">is_strided()</tt>.</p>
<p>Returns: When <tt class="docutils literal">r &lt; rank()</tt> the distance between members
when the index of coordinate <tt class="docutils literal">r</tt> is incremented by one, otherwise 0.</p>
</blockquote>
</div>
<div class="section" id="constructors-assignments-destructor">
<h3>2.2.7&nbsp;&nbsp;&nbsp;Constructors, assignments, destructor</h3>
<p><tt class="docutils literal">constexpr array_ref() noexcept</tt></p>
<blockquote>
Effect: Construct a <em>null</em> <tt class="docutils literal">array_ref</tt> with <tt class="docutils literal">data() == nullptr</tt>
and <tt class="docutils literal">extent(i) == 0</tt> for all dynamic dimensions.</blockquote>
<p><tt class="docutils literal">constexpr array_ref( array_ref const &amp; rhs ) noexcept</tt></p>
<blockquote>
<p>Effect: Construct an <tt class="docutils literal">array_ref</tt> of the same span of objects
referenced by <tt class="docutils literal">rhs</tt>.</p>
<p>Remark: There may be other <tt class="docutils literal"><span class="pre">Properties...</span></tt> dependent effects.</p>
</blockquote>
<p><tt class="docutils literal">constexpr array_ref( array_ref &amp;&amp; rhs ) noexcept</tt></p>
<blockquote>
<p>Effect: Construct an <tt class="docutils literal">array_ref</tt> the span of objects
referenced by <tt class="docutils literal">rhs</tt> and then <tt class="docutils literal">rhs</tt> is a <em>null</em> <tt class="docutils literal">array_ref</tt>.</p>
<p>Remark: There may be other <tt class="docutils literal"><span class="pre">Properties...</span></tt> dependent effects.</p>
</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">array_ref &amp; operator = ( array_ref const &amp; ) noexcept</tt></div>
<div class="line"><tt class="docutils literal">array_ref &amp; operator = ( array_ref &amp;&amp; rhs ) noexcept = default</tt></div>
</div>
<blockquote>
<p>Effect: <tt class="docutils literal">\*this</tt> has equal domain, equal codomain, and
equivalent mapping.</p>
<p>Remark: There may be other <tt class="docutils literal"><span class="pre">Properties...</span></tt> dependent effects.</p>
</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">template&lt; typename UType , typename ... UProperties &gt;</tt></div>
<div class="line"><tt class="docutils literal">constexpr array_ref( array_ref&lt; UType , UProperties ... &gt; const &amp; ) noexcept</tt></div>
<div class="line"><tt class="docutils literal">template&lt; typename UType , typename ... UProperties &gt;</tt></div>
<div class="line"><tt class="docutils literal">array_ref &amp; operator = ( array_ref&lt; UType , UProperties ... &gt; const &amp; ) noexcept</tt></div>
</div>
<blockquote>
<p>Requires:
Given <tt class="docutils literal">using V = <span class="pre">array_ref&lt;DataType,Properties...&gt;</span></tt> and
<tt class="docutils literal">using U = <span class="pre">array_ref&lt;UType,UProperties...&gt;</span></tt> then</p>
<div class="line-block">
<div class="line"><tt class="docutils literal"><span class="pre">is_assignable&lt;V::value_type,U::value_type&gt;</span></tt> ,</div>
<div class="line"><tt class="docutils literal"><span class="pre">V::rank()</span> == <span class="pre">U::rank()</span></tt> ,</div>
<div class="line"><tt class="docutils literal"><span class="pre">V::static_extent(r)</span> == <span class="pre">V::static_extent(r)</span></tt> or <tt class="docutils literal"><span class="pre">V::static_extent(r)</span> == 0</tt> for <tt class="docutils literal">0 &lt;= r &lt; <span class="pre">V::rank()</span></tt> ,</div>
<div class="line">compatibility of layout mapping, and</div>
<div class="line">potentially other property compatibility conditions.</div>
</div>
<p>Effect: <tt class="docutils literal">* this</tt> has equal domain, equal codomain, and
equivalent mapping.</p>
<p>Remark: There may be other <tt class="docutils literal"><span class="pre">Properties...</span></tt> dependent effects.</p>
</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">template&lt; typename ... IntegralExtent &gt;</tt></div>
<div class="line"><tt class="docutils literal">constexpr array_ref( pointer ptr , IntegralExtent ... dynamic_extent) noexcept</tt></div>
</div>
<blockquote>
<p>Requires: <tt class="docutils literal"><span class="pre">conjunction&lt;is_integral&lt;IntegralExtent&gt;::value...&gt;::value</span></tt>.
<tt class="docutils literal"><span class="pre">sizeof...(IntegralExtent)</span> == rank()</tt>.
Each <tt class="docutils literal">dynamic_extent</tt> is non-negative.
The span of objects denoted by <tt class="docutils literal">[ ptr , ptr + <span class="pre">required_span(dynamic_extent...)</span> )</tt>,
shall be a valid contiguous span of objects.</p>
<p>Effects: This <em>wrapping constructor</em> constructs <tt class="docutils literal">* this</tt>
with domain's dynamic extents equal to the input <tt class="docutils literal"><span class="pre">dynamic_extent...</span></tt>
and codomain equal to <tt class="docutils literal">[ ptr .. ptr + <span class="pre">required_span(dynamic_extent...)</span> )</tt></p>
</blockquote>
<p><tt class="docutils literal">constexpr array_ref( pointer ptr , layout const&amp; lay ) noexcept</tt></p>
<blockquote>
<p>Requires:
The span of objects denoted by <tt class="docutils literal">[ ptr , ptr + required_span(lay) )</tt>,
shall be a valid contiguous span of objects.</p>
<p>Effects: This <em>wrapping constructor</em> constructs <tt class="docutils literal">* this</tt>
with domain's dynamic extents extracted from <tt class="docutils literal">lay</tt>
and codomain equal to <tt class="docutils literal">[ ptr .. ptr + <span class="pre">required_span(dynamic_extent...)</span> )</tt></p>
</blockquote>
<p><tt class="docutils literal">~array_ref()</tt></p>
<blockquote>
<p>Effect: Assigns <tt class="docutils literal">this</tt> to be a <em>null</em> <tt class="docutils literal">array_ref</tt>.</p>
<p>Remark: There may be other <tt class="docutils literal"><span class="pre">Properties...</span></tt> dependent effects.</p>
</blockquote>
</div>
</div>
<div class="section" id="subarray">
<h2>2.3&nbsp;&nbsp;&nbsp;<tt class="docutils literal">subarray</tt></h2>
<div class="line-block">
<div class="line"><tt class="docutils literal">template&lt; typename DataType , typename ... Properties , typename ... SliceSpecifiers &gt;</tt></div>
<div class="line"><em>detail::subarray_deduction_t&lt;array_ref&lt;DataType,Properties...&gt;,SliceSpecifiers...&gt;</em></div>
<div class="line"><tt class="docutils literal">subarray( array_ref&lt; DataType, Properties ... &gt; const &amp; U , SliceSpecifiers ... S ) noexcept;</tt></div>
</div>
<blockquote>
<p>The <tt class="docutils literal"><span class="pre">detail::subarray_deduction_t</span></tt> is for exposition only to indicate
that the implementation will require a metafunction to deduce the resulting
<tt class="docutils literal">array_ref</tt> type from the input <tt class="docutils literal">array_ref</tt> and slice specifiers.</p>
<p>Let an <em>integral range</em> be denoted by any of the following.</p>
<ul class="simple">
<li>an <tt class="docutils literal">initializer_list&lt;T&gt;</tt> of integral type <tt class="docutils literal">T</tt> and size 2</li>
<li>a <tt class="docutils literal">pair&lt;T,T&gt;</tt> of integral type <tt class="docutils literal">T</tt></li>
<li>a <tt class="docutils literal">tuple&lt;T,T&gt;</tt>  of integral type <tt class="docutils literal">T</tt></li>
<li>an <tt class="docutils literal">array&lt;T,2&gt;</tt> of integral type <tt class="docutils literal">T</tt></li>
<li><tt class="docutils literal">all</tt> to denote <tt class="docutils literal"><span class="pre">[0..extent(ith))</span></tt></li>
</ul>
<p>Let the <em>ith</em> member of <tt class="docutils literal">S</tt> be denoted by <tt class="docutils literal">S[ith]</tt>.</p>
<p>Requires:
<tt class="docutils literal">U.rank() == <span class="pre">sizeof...(SliceSpecifiers)</span></tt>.
<tt class="docutils literal">S[ith]</tt> is an <em>integral value</em> or an <em>integral range</em>.
If <tt class="docutils literal">S[ith]</tt> is an integral range then let
<tt class="docutils literal">begin(S[ith])</tt> be the beginning of the integral range
<tt class="docutils literal">end(S[ith])</tt> be the end of the integral range.
If <tt class="docutils literal">S[ith]</tt> is an integral value then let
<tt class="docutils literal">begin(S[ith]) == S[ith]</tt> and
<tt class="docutils literal">end(S[ith]) == <span class="pre">S[ith]+1</span></tt>.
<tt class="docutils literal">0 &lt;= begin(S[ith]) &lt;= end(S[ith]) &lt;= A.extent(ith)</tt>.</p>
<p>Returns:  An <tt class="docutils literal">array_ref V</tt> with a domain contained within the domain of <tt class="docutils literal">U</tt> ,
codomain contained within the codomain of <tt class="docutils literal">U</tt> ,
<tt class="docutils literal">V.rank()</tt> is the number of integral ranges in <tt class="docutils literal">SlicedSpecifiers</tt> ,
<tt class="docutils literal">U( <span class="pre">begin(S)...</span> )</tt> refers to the same codomain member
refered to by the mapping the zero-index of <tt class="docutils literal">V</tt> ,
each integral value in <tt class="docutils literal"><span class="pre">S...</span></tt> contracts the corresponding
extent of <tt class="docutils literal">U</tt>.</p>
<p>Example:</p>
</blockquote>
<pre class="code c++ literal-block">
<span class="comment single">// A.rank() == 4 and reference is lvalue reference
</span><span class="keyword type">void</span> <span class="name function">foo</span><span class="punctuation">(</span> <span class="name">array_ref</span><span class="operator">&lt;</span> <span class="name">DataType</span> <span class="punctuation">,</span> <span class="name">Properties</span> <span class="punctuation">...</span> <span class="operator">&gt;</span> <span class="keyword">const</span> <span class="operator">&amp;</span> <span class="name">A</span> <span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="keyword">auto</span> <span class="name">B</span> <span class="operator">=</span> <span class="name">subarray</span><span class="punctuation">(</span> <span class="name">A</span> <span class="punctuation">,</span> <span class="name">make_pair</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">,</span><span class="name">A</span><span class="punctuation">.</span><span class="name">extent</span><span class="punctuation">(</span><span class="literal number integer">0</span><span class="punctuation">)</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">)</span> <span class="punctuation">,</span> <span class="literal number integer">1</span> <span class="punctuation">,</span> <span class="name">make_pair</span><span class="punctuation">(</span><span class="literal number integer">2</span><span class="punctuation">,</span><span class="name">A</span><span class="punctuation">.</span><span class="name">extent</span><span class="punctuation">(</span><span class="literal number integer">2</span><span class="punctuation">)</span> <span class="punctuation">,</span> <span class="literal number integer">2</span> <span class="punctuation">);</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="operator">&amp;</span> <span class="name">B</span><span class="punctuation">(</span><span class="literal number integer">0</span><span class="punctuation">,</span><span class="literal number integer">0</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="name">A</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">,</span><span class="literal number integer">1</span><span class="punctuation">,</span><span class="literal number integer">2</span><span class="punctuation">,</span><span class="literal number integer">2</span><span class="punctuation">)</span> <span class="punctuation">);</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="operator">&amp;</span> <span class="name">B</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">,</span><span class="literal number integer">0</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="name">A</span><span class="punctuation">(</span><span class="literal number integer">2</span><span class="punctuation">,</span><span class="literal number integer">1</span><span class="punctuation">,</span><span class="literal number integer">2</span><span class="punctuation">,</span><span class="literal number integer">2</span><span class="punctuation">)</span> <span class="punctuation">);</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="operator">&amp;</span> <span class="name">B</span><span class="punctuation">(</span><span class="literal number integer">0</span><span class="punctuation">,</span><span class="literal number integer">1</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="name">A</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">,</span><span class="literal number integer">1</span><span class="punctuation">,</span><span class="literal number integer">3</span><span class="punctuation">,</span><span class="literal number integer">2</span><span class="punctuation">)</span> <span class="punctuation">);</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
</div>
</div>
<div class="section" id="multidimensional-array-mapping-and-member-access-properties">
<h1>3&nbsp;&nbsp;&nbsp;Multidimensional Array Mapping and Member Access Properties</h1>
<div class="section" id="header-array-ref-synopsis-for-properties">
<h2>3.1&nbsp;&nbsp;&nbsp;Header <tt class="docutils literal">&lt;array_ref&gt;</tt> synopsis for properties</h2>
<pre class="code c++ literal-block">
<span class="keyword">namespace</span> <span class="name">std</span> <span class="punctuation">{</span>
<span class="keyword">namespace</span> <span class="name">experimental</span> <span class="punctuation">{</span>

  <span class="comment single">// predefined layout mapping properties
</span>  <span class="keyword">struct</span> <span class="name">layout_right</span> <span class="punctuation">;</span>
  <span class="keyword">struct</span> <span class="name">layout_left</span> <span class="punctuation">;</span>
  <span class="keyword">struct</span> <span class="name">layout_stride</span> <span class="punctuation">;</span>

  <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span> <span class="name">T</span><span class="operator">&gt;</span> <span class="keyword">struct</span> <span class="name">is_layout</span> <span class="punctuation">;</span>
  <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span> <span class="name">T</span><span class="operator">&gt;</span> <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_layout_v</span> <span class="operator">=</span> <span class="name">is_layout</span><span class="operator">&lt;</span><span class="name">T</span><span class="operator">&gt;::</span><span class="name">value</span><span class="punctuation">;</span>

  <span class="comment single">// extent size_type property
</span>  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">T</span> <span class="operator">&gt;</span> <span class="keyword">struct</span> <span class="name">extent_size_type</span> <span class="punctuation">;</span>

  <span class="comment single">// bounds checking property
</span>  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword type">bool</span> <span class="name">Enable</span> <span class="operator">&gt;</span>
  <span class="keyword">struct</span> <span class="name">bounds_check_if</span> <span class="punctuation">;</span>

  <span class="keyword">using</span> <span class="name">bounds_check</span> <span class="operator">=</span> <span class="name">bounds_check_if</span><span class="operator">&lt;</span> <span class="name builtin">true</span> <span class="operator">&gt;</span> <span class="punctuation">;</span>

  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="operator">&gt;</span>
  <span class="keyword">struct</span> <span class="name">is_array_property</span> <span class="comment multiline">/* = std::integral_constant&lt;bool,?&gt; */</span> <span class="punctuation">;</span>

  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">T</span> <span class="operator">&gt;</span>
  <span class="keyword">using</span> <span class="name">is_array_property_v</span> <span class="operator">=</span> <span class="name">is_array_property</span><span class="operator">&lt;</span><span class="name">T</span><span class="operator">&gt;::</span><span class="name">value</span> <span class="punctuation">;</span>

<span class="punctuation">}}</span>
</pre>
<!--  -->
</div>
<div class="section" id="layout-mapping">
<h2>3.2&nbsp;&nbsp;&nbsp;Layout Mapping</h2>
<p>An <tt class="docutils literal">array_ref</tt> maps multi-indices from the domain to
reference objects in the codomain by composing a <em>layout mapping</em>
with a span of objects.
The layout mapping is an extension point such that an <tt class="docutils literal">array_ref</tt> may be
instantiated with non-standard layout mappings.</p>
<div class="section" id="standard-layouts">
<h3>3.2.1&nbsp;&nbsp;&nbsp;Standard Layouts</h3>
<p>The <tt class="docutils literal">layout_right</tt> property denotes the C/C++ standard
multidimensional array index mapping
where the right-most extent is stride one and strides increase right-to-left
as the product of extents.
The <tt class="docutils literal">layout_left</tt> property denotes the FORTRAN standard
multidimensional array index mapping
where the left-most extent is stride one and strides increase left-to-right
as the product of extents.
The <tt class="docutils literal">layout_stride</tt> property denotes a multidimensional array index mapping
with arbitrary strides for each extent.</p>
<p>The three standard layouts have the following layout mapping traits.</p>
<p><tt class="docutils literal">layout_right</tt> ; i.e., the C/C++ standard layout</p>
<blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">is_always_unique == true</tt></div>
<div class="line"><tt class="docutils literal">is_always_contiguous == true</tt></div>
<div class="line"><tt class="docutils literal">is_always_strided == true</tt></div>
<div class="line">When <tt class="docutils literal">0 &lt; rank()</tt> then <tt class="docutils literal"><span class="pre">stride(rank()-1)</span> == 1</tt> .</div>
<div class="line">When <tt class="docutils literal">1 &lt; rank()</tt> then <tt class="docutils literal"><span class="pre">stride(r-1)</span> = stride(r) * extent(r)</tt> for <tt class="docutils literal">0 &lt; r &lt; rank()</tt> ..</div>
</div>
<p>For rank-two arrays (a.k.a., matrices) this is also known as <em>row major</em> layout.</p>
</blockquote>
<p><tt class="docutils literal">layout_left</tt> ; i.e., the FORTRAN standard layout</p>
<blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">is_always_unique == true</tt></div>
<div class="line"><tt class="docutils literal">is_always_contiguous == true</tt></div>
<div class="line"><tt class="docutils literal">is_always_strided == true</tt></div>
<div class="line">When <tt class="docutils literal">0 &lt; rank()</tt> then <tt class="docutils literal">stride(0) == 1</tt> .</div>
<div class="line">When <tt class="docutils literal">1 &lt; rank()</tt> then <tt class="docutils literal">stride(r) = <span class="pre">stride(r-1)</span> * <span class="pre">extent(r-1)</span></tt> for <tt class="docutils literal">0 &lt; r &lt; rank()</tt> ..</div>
</div>
<p>For rank-two arrays (a.k.a., matrices) this is also known as <em>column major</em> layout.</p>
</blockquote>
<p><tt class="docutils literal">layout_stride</tt> ; i.e., an arbitrary <strong>strided</strong> layout</p>
<blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">is_always_unique == false</tt></div>
<div class="line"><tt class="docutils literal">is_always_contiguous == false</tt></div>
<div class="line"><tt class="docutils literal">is_always_strided == true</tt></div>
</div>
</blockquote>
</div>
<div class="section" id="concept-for-extensible-layout-mapping">
<h3>3.2.2&nbsp;&nbsp;&nbsp;Concept for Extensible Layout Mapping</h3>
<p>A <em>layout</em> class conforms to the following interface such that an
<tt class="docutils literal">array_ref</tt> can compose the layout mapping with its <tt class="docutils literal">array_ref</tt>
codomain member reference generation.</p>
<pre class="code c++ literal-block">
<span class="keyword">class</span> <span class="name class">layout_concept</span> <span class="comment multiline">/* exposition only */</span> <span class="punctuation">{</span>
<span class="keyword">public</span><span class="operator">:</span>

  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">ExtentType</span> <span class="punctuation">,</span> <span class="name">ExtentType</span> <span class="punctuation">...</span> <span class="operator">&gt;</span>
  <span class="keyword">class</span> <span class="name class">mapping</span> <span class="punctuation">{</span>
  <span class="keyword">public</span><span class="operator">:</span>

    <span class="comment single">// domain types
</span>
    <span class="keyword">using</span> <span class="name">size_type</span> <span class="operator">=</span> <span class="name">ExtentType</span> <span class="punctuation">;</span>

    <span class="comment single">// constructors, copy, assignment, and destructor
</span>
    <span class="keyword">constexpr</span> <span class="name">mapping</span><span class="punctuation">()</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>
    <span class="keyword">constexpr</span> <span class="name">mapping</span><span class="punctuation">(</span><span class="name">mapping</span><span class="operator">&amp;&amp;</span><span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>
    <span class="keyword">constexpr</span> <span class="name">mapping</span><span class="punctuation">(</span><span class="name">mapping</span> <span class="keyword">const</span><span class="operator">&amp;</span><span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>
    <span class="name">mapping</span><span class="operator">&amp;</span> <span class="keyword">operator</span><span class="operator">=</span><span class="punctuation">(</span><span class="name">mapping</span><span class="operator">&amp;&amp;</span><span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>
    <span class="name">mapping</span><span class="operator">&amp;</span> <span class="keyword">operator</span><span class="operator">=</span><span class="punctuation">(</span><span class="name">mapping</span> <span class="keyword">const</span><span class="operator">&amp;</span><span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>

    <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span><span class="punctuation">...</span> <span class="name">IntegralExtent</span><span class="operator">&gt;</span>
    <span class="keyword">explicit</span> <span class="keyword">constexpr</span> <span class="name">mapping</span><span class="punctuation">(</span> <span class="name">IntegralExtent</span><span class="punctuation">...</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="keyword">explicit</span> <span class="keyword">constexpr</span> <span class="name">mapping</span><span class="punctuation">(</span> <span class="name">layout_concept</span> <span class="keyword">const</span><span class="operator">&amp;</span><span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="operator">~</span><span class="name">mapping</span><span class="punctuation">()</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>

    <span class="comment single">// observers of domain: [0..extent(0)) X [0..extent(1)) X ... X [0..extent(rank()-1))
</span>
    <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">int</span> <span class="name">rank</span><span class="punctuation">()</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>
    <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">int</span> <span class="name">rank_dynamic</span><span class="punctuation">()</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">size</span><span class="punctuation">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">extent</span><span class="punctuation">(</span><span class="keyword type">int</span><span class="punctuation">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">static_extent</span><span class="punctuation">(</span><span class="keyword type">int</span><span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="comment single">// observers of the codomain: [0..span())
</span>
    <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">span</span><span class="punctuation">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span><span class="punctuation">...</span> <span class="name">IntegralExtent</span><span class="operator">&gt;</span>
    <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">required_span</span><span class="punctuation">(</span> <span class="name">IntegralExtent</span> <span class="punctuation">...</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">required_span</span><span class="punctuation">(</span> <span class="name">layout_concept</span> <span class="keyword">const</span> <span class="operator">&amp;</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="comment single">// observers of the mapping from domain to codomain
</span>
    <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_always_unique</span>     <span class="operator">=</span> <span class="comment multiline">/* deduced */</span> <span class="punctuation">;</span>
    <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_always_contiguous</span> <span class="operator">=</span> <span class="comment multiline">/* deduced */</span> <span class="punctuation">;</span>
    <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_always_strided</span>    <span class="operator">=</span> <span class="comment multiline">/* deduced */</span> <span class="punctuation">;</span>

    <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_unique</span><span class="punctuation">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>
    <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_contiguous</span><span class="punctuation">()</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>
    <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_strided</span><span class="punctuation">()</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">stride</span><span class="punctuation">(</span><span class="keyword type">int</span><span class="punctuation">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="comment single">// mapping domain index to access codomain element
</span>
    <span class="keyword">template</span> <span class="operator">&lt;</span><span class="keyword">typename</span><span class="punctuation">...</span> <span class="name">IntegralIndex</span><span class="operator">&gt;</span>
    <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="keyword">operator</span><span class="punctuation">()(</span><span class="name">IntegralIndex</span><span class="punctuation">...)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>
  <span class="punctuation">};</span>
<span class="punctuation">};</span>
</pre>
<!--  -->
<p><tt class="docutils literal">template&lt; typename ExtentType , ExtentType ... Extent &gt; class mapping</tt></p>
<blockquote>
<p>Requires: <tt class="docutils literal">is_integral&lt;ExtentType&gt;</tt> and <tt class="docutils literal">Extent</tt> is non-negative.</p>
<p>Effects: Defines the domain index space where
<tt class="docutils literal">rank() == <span class="pre">sizeof...(Extent)</span></tt> and each <tt class="docutils literal">Extent == 0</tt>
denotes a dynamic dimension.</p>
</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">constexpr mapping() noexcept;</tt></div>
<div class="line"><tt class="docutils literal">constexpr <span class="pre">mapping(mapping&amp;&amp;)</span> noexcept ;</tt></div>
<div class="line"><tt class="docutils literal">constexpr mapping(mapping const&amp;) noexcept ;</tt></div>
<div class="line"><tt class="docutils literal">mapping&amp; <span class="pre">operator=(mapping&amp;&amp;)</span> noexcept ;</tt></div>
<div class="line"><tt class="docutils literal">mapping&amp; <span class="pre">operator=(mapping</span> const&amp;) noexcept ;</tt></div>
</div>
<blockquote>
Customary constructors and assignment operators.</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">template <span class="pre">&lt;typename...</span> IntegralExtent&gt;</tt></div>
<div class="line"><tt class="docutils literal">explicit constexpr mapping( <span class="pre">IntegralExtent...</span> ) noexcept;</tt></div>
<div class="line"><tt class="docutils literal">explicit constexpr mapping( layout_concept const&amp;) noexcept;</tt></div>
<div class="line"><br /></div>
<div class="line"><tt class="docutils literal">~mapping() noexcept ;</tt></div>
</div>
<blockquote>
Constructors, assignment operators, and destructor requires and effects
correspond to the corresponding members of <tt class="docutils literal">array_ref</tt> .</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">static constexpr int rank() noexcept;</tt></div>
<div class="line"><tt class="docutils literal">static constexpr int rank_dynamic() noexcept;</tt></div>
<div class="line"><tt class="docutils literal">constexpr size_type size() const noexcept;</tt></div>
<div class="line"><tt class="docutils literal">constexpr size_type extent(int) const noexcept;</tt></div>
<div class="line"><tt class="docutils literal">constexpr size_type static_extent(int) noexcept;</tt></div>
<div class="line"><tt class="docutils literal">constexpr size_type span() const noexcept;</tt></div>
<div class="line"><br /></div>
<div class="line"><tt class="docutils literal">template <span class="pre">&lt;typename...</span> IntegralExtent&gt;</tt></div>
<div class="line"><tt class="docutils literal">static constexpr size_type required_span( IntegralExtent ... ) noexcept;</tt></div>
<div class="line"><tt class="docutils literal">static constexpr size_type required_span( layout_concept const &amp; ) noexcept;</tt></div>
<div class="line"><br /></div>
<div class="line"><tt class="docutils literal">static constexpr bool is_always_unique&nbsp;&nbsp;&nbsp;&nbsp; = /* deduced */ ;</tt></div>
<div class="line"><tt class="docutils literal">static constexpr bool is_always_contiguous = /* deduced */ ;</tt></div>
<div class="line"><tt class="docutils literal">static constexpr bool is_always_strided&nbsp;&nbsp;&nbsp; = /* deduced */ ;</tt></div>
<div class="line"><br /></div>
<div class="line"><tt class="docutils literal">constexpr bool is_unique() const noexcept;</tt></div>
<div class="line"><tt class="docutils literal">constexpr bool is_contiguous() const noexcept;</tt></div>
<div class="line"><tt class="docutils literal">constexpr bool is_strided() noexcept;</tt></div>
<div class="line"><br /></div>
<div class="line"><tt class="docutils literal">constexpr size_type stride(int) const noexcept;</tt></div>
</div>
<blockquote>
Domain, codomain, and mapping observers requires and effects
correspond to the corresponding members of <tt class="docutils literal">array_ref</tt> .</blockquote>
<div class="line-block">
<div class="line"><tt class="docutils literal">template <span class="pre">&lt;typename...</span> IntegralIndex&gt;</tt></div>
<div class="line"><tt class="docutils literal">constexpr size_type <span class="pre">operator()(IntegralIndex...index)</span> const noexcept;</tt></div>
</div>
<blockquote>
<p>Requires: <tt class="docutils literal">rank() == <span class="pre">sizeof...(IntegralIndex)</span></tt> and
<tt class="docutils literal">0 &lt;= index[ith] &lt; extent(ith)</tt>.</p>
<p>Returns: Layout mapping of <tt class="docutils literal"><span class="pre">index...</span></tt> to codomain.</p>
</blockquote>
</div>
</div>
<div class="section" id="property-extent-size-type-integral">
<h2>3.3&nbsp;&nbsp;&nbsp;Property: <tt class="docutils literal">extent_size_type&lt;</tt> <em>integral</em> <tt class="docutils literal">&gt;</tt></h2>
<p><tt class="docutils literal">template&lt; typename</tt> <em>integral</em> <tt class="docutils literal">&gt; struct extent_size_type ;</tt></p>
<blockquote>
Requires: <tt class="docutils literal">is_integral&lt;</tt> <em>integral</em> <tt class="docutils literal">&gt;</tt>.
Specify <tt class="docutils literal"><span class="pre">array_ref::size_type</span></tt> as <em>integral</em> .
If unspecified then <tt class="docutils literal"><span class="pre">array_ref::size_type</span></tt> is <tt class="docutils literal">size_t ;</tt> .</blockquote>
</div>
<div class="section" id="property-bounds-check-if-bool">
<h2>3.4&nbsp;&nbsp;&nbsp;Property: <tt class="docutils literal">bounds_check_if&lt; bool &gt;</tt></h2>
<div class="line-block">
<div class="line"><tt class="docutils literal">template&lt; bool Enable &gt; struct bounds_check_if ;</tt></div>
<div class="line"><tt class="docutils literal">using bounds_check = bounds_check&lt;true&gt; ;</tt></div>
</div>
<blockquote>
When <tt class="docutils literal">array_ref</tt> <tt class="docutils literal"><span class="pre">Properties...</span></tt> includes
<tt class="docutils literal">bounds_check_if&lt;true&gt;</tt> then the mapping operators
<tt class="docutils literal"><span class="pre">array_ref::operator()</span></tt> and <tt class="docutils literal"><span class="pre">array_ref::operator[]</span></tt>
verify that each index is valid,
<tt class="docutils literal">0 &lt;= index[ith] &lt; extent(ith)</tt>.
Verification failure shall be reported.</blockquote>
</div>
</div>
<div class="section" id="undesirable-extent-mechanism-b-proposal">
<h1>4&nbsp;&nbsp;&nbsp;Undesirable Extent Mechanism (B) Proposal</h1>
<p>The <tt class="docutils literal">extents</tt> struct and <tt class="docutils literal">dyn</tt> value are only required for the
undesirable extents specification mechanism B.</p>
<pre class="code c++ literal-block">
<span class="keyword">namespace</span> <span class="name">std</span> <span class="punctuation">{</span>
<span class="keyword">namespace</span> <span class="name">experimental</span> <span class="punctuation">{</span>

  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword type">size_t</span> <span class="punctuation">...</span> <span class="name">IntegralExtent</span> <span class="operator">&gt;</span>
  <span class="keyword">struct</span> <span class="name">extents</span> <span class="punctuation">{</span>

    <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">int</span> <span class="name">rank</span><span class="punctuation">()</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>
    <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">int</span> <span class="name">rank_dynamic</span><span class="punctuation">()</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

    <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">size_t</span> <span class="name">static_extent</span><span class="punctuation">(</span><span class="keyword type">int</span><span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>
  <span class="punctuation">};</span>

  <span class="keyword">constexpr</span> <span class="keyword type">size_t</span> <span class="name">dyn</span> <span class="operator">=</span> <span class="literal number integer">0</span> <span class="punctuation">;</span> <span class="comment single">// or ~size_t(0)
</span>
<span class="punctuation">}}</span>
</pre>
<!--  -->
<blockquote>
Effects:
| <tt class="docutils literal">IntegralExtent == dyn</tt> indicates a dynamic extent.
| <tt class="docutils literal">rank() == <span class="pre">sizeof...(IntegralExtent)</span></tt>
| <tt class="docutils literal">rank_dynamic()</tt> is the number of dynamic extents.
| <tt class="docutils literal">static_extent(r) == IntegralExtent[r]</tt></blockquote>
</div>
<div class="section" id="future-directions-and-extensions">
<h1>5&nbsp;&nbsp;&nbsp;Future Directions and Extensions</h1>
</div>
<div class="section" id="revision-history">
<h1>6&nbsp;&nbsp;&nbsp;Revision History</h1>
<div class="section" id="p0009r0">
<h2>6.1&nbsp;&nbsp;&nbsp;P0009r0</h2>
<p>Original multidimensional array reference paper with
motivation, specification, and examples.</p>
</div>
<div class="section" id="p0009r1">
<h2>6.2&nbsp;&nbsp;&nbsp;P0009r1</h2>
<p>Revised with renaming from <tt class="docutils literal">view</tt> to <tt class="docutils literal">array_ref</tt>
and allow unbounded rank through variadic arguments.</p>
</div>
<div class="section" id="p0009r2">
<h2>6.3&nbsp;&nbsp;&nbsp;P0009r2</h2>
<p>Adding details for extensibility of layout mapping.</p>
<p>Move motivation, examples, and relaxed incomplete array type proposal to separate papers.</p>
<blockquote>
<ul class="simple">
<li>P0331 : Motivation and Examples for Polymorphic Multidimensional Array</li>
<li>P0332 : Relaxed Incomplete Multidimensional Array Type Declaration</li>
</ul>
</blockquote>
</div>
<div class="section" id="p0009r3">
<h2>6.4&nbsp;&nbsp;&nbsp;P0009r3</h2>
<p>Oulu-2016 LEWG strawpoll: Move iterator from this paper to a subsequent paper.</p>
<p>Oulu-2016 LEWG feedback: <a class="reference external" href="http://wiki.edg.com/bin/view/Wg21oulu/P0009">http://wiki.edg.com/bin/view/Wg21oulu/P0009</a></p>
<blockquote>
<ul class="simple">
<li>Array extents specification mechanism options are either-or, not both.</li>
<li>List potential names for LEWG and/or LWG todo bikeshedding.</li>
<li>Clearly &amp; concisely note difference between multidimensional array versus language's array-of-array-of-array...</li>
<li>Actual specification of reference type (and others), not &quot;typically is&quot; vagueness.</li>
<li>Future directions / extensibility section regarding <tt class="docutils literal"><span class="pre">Properties...</span></tt></li>
</ul>
</blockquote>
<p>The domain space specification <em>preferred</em> and <em>undesirable</em> mechanisms
changed from accepting both to accepting only one.</p>
<p>Tighten up domain, codomain, and domain -&gt; codomain mapping specifications.</p>
<p>Consistently use <em>extent</em> and <em>extents</em> for the multidimensional index space.</p>
</div>
<div class="section" id="future-reversion">
<h2>6.5&nbsp;&nbsp;&nbsp;Future reversion</h2>
<p>Align with and extend layout properties of
P0454, Wording for Minimal <tt class="docutils literal">mdspan</tt>.</p>
</div>
</div>
<div class="section" id="references">
<h1>7&nbsp;&nbsp;&nbsp;References</h1>
<p>ISOCPP issue: <a class="reference external" href="https://issues.isocpp.org/show_bug.cgi?id=80">https://issues.isocpp.org/show_bug.cgi?id=80</a></p>
<div class="section" id="p0454-wording-for-a-minimal-mdspan">
<h2>7.1&nbsp;&nbsp;&nbsp;P0454 : Wording for a Minimal <tt class="docutils literal">mdspan</tt></h2>
<p>The <tt class="docutils literal">mdspan</tt> is a minimal version of the multidimensional array view
capability.</p>
</div>
<div class="section" id="p0122-span-bounds-safe-views-for-sequences-of-objects">
<h2>7.2&nbsp;&nbsp;&nbsp;P0122 : span: bounds-safe views for sequences of objects</h2>
<p>The <tt class="docutils literal">array_ref</tt> codomain concept of <em>span</em> is well-aligned with this paper.</p>
</div>
<div class="section" id="p0367-accessors">
<h2>7.3&nbsp;&nbsp;&nbsp;P0367 : Accessors</h2>
<p>The P0367 Accessors proposal includes polymorphic mechanisms for
accessing the memory an object or span of objects.
The <tt class="docutils literal"><span class="pre">Properties...</span></tt> extension point in this proposal is intended
to include such memroy access properties.</p>
</div>
</div>
</div>
</body>
</html>
