<?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>P0009r1 : Polymorphic Multidimensional Array Reference</title>
<meta name="date" content="2016-02-04" />
<meta name="author" content="H. Carter Edwards" />
<meta name="author" content="Bryce Lelbach" />
<meta name="author" content="Christian Trott" />
<meta name="author" content="Juan Alday" />
<meta name="author" content="Jesse Perla" />
<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="p0009r1-polymorphic-multidimensional-array-reference">
<h1 class="title">P0009r1 : 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">P0009r1</td>
</tr>
<tr><th class="docinfo-name">Date:</th>
<td>2016-02-04</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>Juan Alday</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:juanalday&#64;gmail.com">juanalday&#64;gmail.com</a></td></tr>
<tr><th class="docinfo-name">Author:</th>
<td>Jesse Perla</td></tr>
<tr><th class="docinfo-name">Contact:</th>
<td><a class="first last reference external" href="mailto:jesse.perla&#64;ubc.ca">jesse.perla&#64;ubc.ca</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">Audience:</th><td class="field-body">Evolution Working Group (EWG) for concise array declaration</td>
</tr>
<tr class="field"><th class="docinfo-name">URL:</th><td class="field-body"><a class="reference external" href="https://github.com/kokkos/PolyView/blob/master/P0009.rst">https://github.com/kokkos/PolyView/blob/master/P0009.rst</a></td>
</tr>
</tbody>
</table>
<div class="section" id="rationale-for-polymorphic-multidimensional-array-reference">
<h1>1&nbsp;&nbsp;&nbsp;Rationale for polymorphic multidimensional array reference</h1>
<p>Multidimensional arrays are a foundational data structure
for science and engineering codes, as demonstrated by their
extensive use in FORTRAN for five decades.
A <em>multidimensional array reference</em> is a reference to a memory extent
through a <strong>layout</strong> mapping from a multi-index space (domain) to
that extent (range).
A array layout mapping may be bijective as in the case of a traditional
multidimensional array, injective as in the case of a subarray, or
surjective to express symmetry.</p>
<p>Traditional layout mappings have been specfied as part of the language.
For example, FORTRAN specifies <em>column major</em> layout and
C specifies <em>row major</em> layout.
Such a language-imposed specification requires signficant code refactoring
to change an array's layout, and requires significant code complexity to
implement non-traditional layouts such as tiling in modern linear algebra
or structured grid application domains.  Such layout changes are required
to adapt and optimize code for varying computer architectures; for example,
to change a code from <em>array of structures</em> to <em>structure of arrays</em>.
Furthermore, multiple versions of code must be maintained for each required layout.</p>
<p>A multidimensional array reference abstraction
with a polymorphic layout is required
to enable changing array layouts without extensive code refactoring and
maintenance of functionally redundant code.
Layout polymorphism is a critical capability; however, it is not the only
beneficial form of polymorphism.</p>
<p>The Kokkos library (github.com/kokkos/kokkos) implements
multidimensional array references with polymorphic layout,
and other access properties as well.
Until recently the Kokkos implementation was limited
to C++1998 standard and is incrementally being refactored
to C++2011 standard.
Additionally, there is a standalone reference implementation of this proposal
which is publicly available on github (github.com/brycelelbach/array_ref).</p>
</div>
<div class="section" id="extensibility-beyond-multdimensional-array-layout">
<h1>2&nbsp;&nbsp;&nbsp;Extensibility beyond multdimensional array layout</h1>
<p>The polymorphic <strong>array_ref</strong> abstraction and interface has utility
well beyond the multidimensional array layout property.
Other planned and prototyped properties include specification
of which <em>memory space</em> within a heterogeneous memory system
the referenced data resides on and algorithmic access intent properties.
Examples of access intent properties include</p>
<blockquote>
<ol class="arabic simple">
<li><em>read-only random with locality</em> such that member queries are
performed through GPU texture cache hardware for GPU memory spaces,</li>
<li><em>atomic</em> such that member access operations are overloaded
via proxy objects to atomic operations (see P0019, Atomic View),</li>
<li><em>non-temporal</em> such that member access operations can be overloaded
with non-caching reads and writes, and</li>
<li><em>restrict</em> to guarantee non-aliasing of referenced data within the
current context.</li>
</ol>
</blockquote>
</div>
<div class="section" id="compare-and-contrast-summary-previous-array-view-proposals">
<h1>3&nbsp;&nbsp;&nbsp;Compare and contrast summary: previous <strong>array_view</strong> proposals</h1>
<p>The essential issue with <strong>array_view</strong> in
N4512 &quot;Multidimensional bounds, offset and array_view, revision 7&quot;
is that it did not fulfill C++'s <em>zero-overhead abstraction</em> requirement
(for both dynamic and static extents), and does not provide a
zero-overhead abstraction to different memory layouts which are
essential for library interoperability with a variety of C++ (e.g. Eigen)
and other languages (e.g. Fortran and Matlab's C++ interface).
Were it to be accepted, another library would be necessary to provide
&quot;direct mapping to the hardware&quot; for views of arrays.
Many of the issues are discussed in more detail in N4355, N4300, and N4222.</p>
<dl class="docutils">
<dt>Unlike N4512, this proposal</dt>
<dd><ul class="first last simple">
<li>allows the layout to be more general with different orderings and padding essential for performant member access (<em>e.g.</em>, caching, coalescing),</li>
<li>enables interoperability with libraries using compile-time extents, and</li>
<li>achieves zero-overhead abstraction for <em>constexpr</em> extents and strides which provides more opportunities for the compiler to optimize array data member access functions.</li>
</ul>
</dd>
</dl>
<p>The P0122 &quot;array_view: bounds-safe views for sequences of objects&quot; proposal is
largely compatible with this proposal but only supports 1-dimensional array
references or layout polymorphism, and thus does not address the entire problem
space.</p>
</div>
<div class="section" id="array-reference">
<h1>4&nbsp;&nbsp;&nbsp;Array Reference</h1>
<p>The proposed <strong>array_ref</strong> has template arguments for the data type of the array
and a parameter pack for polymorphic properties of the reference.</p>
<blockquote>
<div class="line-block">
<div class="line">namespace std {</div>
<div class="line">namespace experimental {</div>
<div class="line-block">
<div class="line">template&lt; typename DataType , typename ... Properties &gt;</div>
<div class="line">struct array_ref ;</div>
</div>
<div class="line">}}</div>
</div>
</blockquote>
<p>The complete proposed specification for <strong>array_ref</strong> is
included at the end of this paper.
We present the specification incrementally to
convey the rational for this specification.</p>
<p>An initial set of properties are proposed.
These properties are defined by class types
and reside in the <strong>array_property</strong> namespace,
similar to the namespaces for <strong>std::rel_ops</strong> functions,
<strong>std::chrono</strong> classes, or <strong>std::regex_constants</strong> constants.</p>
<blockquote>
<div class="line-block">
<div class="line">namespace std {</div>
<div class="line">namespace experimental {</div>
<div class="line">namespace array_property {</div>
<div class="line-block">
<div class="line">// array property classes</div>
</div>
<div class="line">}}}</div>
</div>
</blockquote>
</div>
<div class="section" id="one-dimensional-array">
<h1>5&nbsp;&nbsp;&nbsp;One-Dimensional Array</h1>
<p>A reference to a one-dimension array is anticipated to subsume the functionality
of a pointer to a memory extent combined with an array length.
For example, a one-dimensional array is passed to a function as follows.</p>
<pre class="code c++ literal-block">
<span class="keyword type">void</span> <span class="name function">foo</span><span class="punctuation">(</span> <span class="keyword type">int</span> <span class="name">A</span><span class="punctuation">[]</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N</span> <span class="punctuation">);</span> <span class="comment single">// Traditional API
</span><span class="keyword type">void</span> <span class="name function">foo</span><span class="punctuation">(</span> <span class="keyword">const</span> <span class="keyword type">int</span> <span class="name">A</span><span class="punctuation">[]</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N</span> <span class="punctuation">);</span> <span class="comment single">// Traditional API
</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="keyword type">int</span><span class="punctuation">[]</span> <span class="operator">&gt;</span> <span class="name">A</span> <span class="punctuation">);</span> <span class="comment single">// Reference API
</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="keyword">const</span> <span class="keyword type">int</span><span class="punctuation">[]</span> <span class="operator">&gt;</span> <span class="name">A</span> <span class="punctuation">);</span> <span class="comment single">// Reference API
</span>
<span class="keyword type">void</span> <span class="name function">bar</span><span class="punctuation">()</span>
<span class="punctuation">{</span>
  <span class="keyword">enum</span> <span class="punctuation">{</span> <span class="name">L</span> <span class="operator">=</span> <span class="punctuation">...</span> <span class="punctuation">};</span>
  <span class="keyword type">int</span> <span class="name">buffer</span><span class="punctuation">[</span> <span class="name">L</span> <span class="punctuation">];</span>
  <span class="name">array_ref</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="punctuation">[]</span><span class="operator">&gt;</span> <span class="name">A</span><span class="punctuation">(</span> <span class="name">buffer</span> <span class="punctuation">,</span> <span class="name">L</span> <span class="punctuation">);</span>

  <span class="name">assert</span><span class="punctuation">(</span> <span class="name">L</span> <span class="operator">==</span> <span class="name">A</span><span class="punctuation">.</span><span class="name">size</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">A</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>

  <span class="name">foo</span><span class="punctuation">(</span> <span class="name">array</span> <span class="punctuation">);</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
<p>The <em>const-ness</em> of an <strong>array_ref</strong> is analogous to the <em>const-ness</em>
of a pointer.
A <strong>const array_ref&lt;D&gt;</strong> is similar to a const-pointer in that the <strong>array_ref</strong>
may not be modifid but the referenced extent of memory may be modified.
A <strong>array_ref&lt;const D&gt;</strong> is similar to a pointer-to-const in that the
referenced extent of memory may not be modified. These are the same <em>const-ness</em>
semantics of <strong>unique_ptr</strong> and <strong>shared_ptr</strong>.</p>
<p>The <strong>T[]</strong> syntax has precedence in the standard; <strong>unique_ptr</strong> supports this
syntax to denote a <strong>unique_ptr</strong> which manages the lifetime of a dynamically
allocated array of objects.</p>
</div>
<div class="section" id="traditional-multidimensional-array-with-explicit-dimensions">
<h1>6&nbsp;&nbsp;&nbsp;Traditional Multidimensional Array with Explicit Dimensions</h1>
<p>A traditional multidimensional array with explicit dimensions
(for example, an array of 3x3 tensors) is passed to a function as follows.</p>
<pre class="code c++ literal-block">
<span class="keyword type">void</span> <span class="name function">foo</span><span class="punctuation">(</span> <span class="keyword type">double</span> <span class="name">A</span><span class="punctuation">[][</span><span class="literal number integer">3</span><span class="punctuation">][</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N0</span> <span class="punctuation">);</span> <span class="comment single">// Traditional API
</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="keyword type">double</span><span class="punctuation">[][</span><span class="literal number integer">3</span><span class="punctuation">][</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">&gt;</span> <span class="name">A</span> <span class="punctuation">);</span> <span class="comment single">// Reference API
</span>
<span class="keyword type">void</span> <span class="name function">bar</span><span class="punctuation">()</span>
<span class="punctuation">{</span>
  <span class="keyword">enum</span> <span class="punctuation">{</span> <span class="name">L</span> <span class="operator">=</span> <span class="punctuation">...</span> <span class="punctuation">};</span>
  <span class="keyword type">int</span> <span class="name">buffer</span><span class="punctuation">[</span> <span class="name">L</span> <span class="operator">*</span> <span class="literal number integer">3</span> <span class="operator">*</span> <span class="literal number integer">3</span> <span class="punctuation">];</span>
  <span class="name">array_ref</span><span class="operator">&lt;</span> <span class="keyword type">double</span><span class="punctuation">[][</span><span class="literal number integer">3</span><span class="punctuation">][</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">&gt;</span> <span class="name">A</span><span class="punctuation">(</span> <span class="name">buffer</span> <span class="punctuation">,</span> <span class="name">L</span> <span class="punctuation">);</span>

  <span class="name">assert</span><span class="punctuation">(</span> <span class="literal number integer">3</span> <span class="operator">==</span> <span class="name">A</span><span class="punctuation">.</span><span class="name">rank</span><span class="punctuation">()</span> <span class="punctuation">);</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="name">L</span> <span class="operator">==</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="punctuation">);</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="literal number integer">3</span> <span class="operator">==</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="punctuation">);</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="literal number integer">3</span> <span class="operator">==</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="name">assert</span><span class="punctuation">(</span> <span class="name">A</span><span class="punctuation">.</span><span class="name">size</span><span class="punctuation">()</span> <span class="operator">==</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">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="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="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>

  <span class="name">foo</span><span class="punctuation">(</span> <span class="name">A</span> <span class="punctuation">);</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
</div>
<div class="section" id="multidimensional-array-with-multiple-implicit-dimensions">
<h1>7&nbsp;&nbsp;&nbsp;Multidimensional Array with Multiple Implicit Dimensions</h1>
<p>The current multidimensional array type declaration in <strong>n4567 8.3.4.p3</strong>
restricts array declarations such that only the leading dimension
may be implicit.
Multidimensional arrays with multiple implicit dimensions as well as
explicit dimensions are supported with the <strong>dimension</strong> property.
The dimension property uses the &quot;magic value&quot; zero to denote an
implicit dimension.
The &quot;magic value&quot; of zero is chosen for consistency with <strong>std::extent</strong>.</p>
<pre class="code c++ literal-block">
<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">3</span><span class="punctuation">]</span> <span class="operator">&gt;</span> <span class="name">x</span> <span class="punctuation">;</span>

<span class="name">assert</span><span class="punctuation">(</span> <span class="name">x</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">0</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">x</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">3</span> <span class="punctuation">);</span>

<span class="name">assert</span><span class="punctuation">(</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">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="name">assert</span><span class="punctuation">(</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">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">0</span> <span class="punctuation">);</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">array_property</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</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">3</span><span class="operator">&gt;</span> <span class="operator">&gt;</span> <span class="name">y</span> <span class="punctuation">;</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">y</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">0</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">y</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">0</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">y</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="name">array_ref</span><span class="operator">&lt;</span> <span class="keyword type">int</span> <span class="punctuation">,</span> <span class="name">array_proprety</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</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">3</span><span class="operator">&gt;</span> <span class="operator">&gt;</span> <span class="name">z</span><span class="punctuation">(</span><span class="name">ptr</span><span class="punctuation">,</span><span class="name">N0</span><span class="punctuation">,</span><span class="name">N1</span><span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">z</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">N0</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">z</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="name">N1</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">z</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>
</pre>
<!--  -->
<div class="section" id="preferred-syntax">
<h2>7.1&nbsp;&nbsp;&nbsp;Preferred Syntax</h2>
<p>We prefer the following concise and intuitive syntax for arrays
with multiple implict dimensions.</p>
<pre class="code c++ literal-block">
<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">3</span><span class="punctuation">]</span> <span class="operator">&gt;</span> <span class="name">y</span> <span class="punctuation">;</span> <span class="comment single">// concise intuitive syntax</span>
</pre>
<!--  -->
<p>However, this syntax requires a
<a class="reference internal" href="#relaxation-of-the-current-multidimensional-array-type-declaration">relaxation of the current multidimensional array type declaration</a>
in <strong>n4567 8.3.4.p3</strong>.
Furthermore, this concise and intuitive syntax eliminates the need
for <tt class="docutils literal"><span class="pre">array_property::dimension&lt;...&gt;</span></tt> and the associated &quot;magic value&quot;
of zero to denote an implicit dimension.</p>
</div>
</div>
<div class="section" id="array-reference-properties-layout-polymorphism">
<h1>8&nbsp;&nbsp;&nbsp;Array Reference Properties: Layout Polymorphism</h1>
<p>The <strong>array_ref::operator()</strong> maps the input multi-index from the array's
cartesian product multi-index <em>domain</em> space to a member in the array's <em>range</em> space.
This is the <strong>layout</strong> mapping for the referenced array.
For natively declared multidimensional arrays the layout mapping
is defined to conform to treating the multidimensional array as
an <em>array of arrays of arrays ...</em>; i.e., the size and span are
equal and the strides increase from right-to-left (the layout specified in the
C language).
In the FORTRAN language defines layout mapping with strides
increasing from left-to-right.
These <em>native</em> layout mappings are only two of many possible layouts.
For example, the <em>basic linear algebra subprograms (BLAS)</em> standard
defines dense matrix layout mapping with padding of the leading dimension,
requiring both dimensions and <strong>LDA</strong> parameters to fully declare a matrix layout.</p>
<p>A property template parameter specifies a layout mapping.
If this property is omitted the layout mapping of the array reference
conforms to a corresponding natively declared multidimensional array
as if implicit dimensions were declared explicitly.
The default layout is <em>regular</em> - the distance is constant between
entries when a single index of the multi-index is incremented.
This distance is the <em>stride</em> of the corresponding dimension.
The default layout mapping is bijective and the stride increases
monotonically from the right most to the left most dimension.</p>
<pre class="code c++ literal-block">
<span class="comment single">// The default layout mapping of a rank-four multidimensional
// array is as if implemented as follows.
</span>
<span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword type">size_t</span> <span class="name">N0</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N1</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N2</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N3</span> <span class="operator">&gt;</span>
<span class="keyword type">size_t</span> <span class="name">native_mapping</span><span class="punctuation">(</span> <span class="keyword type">size_t</span> <span class="name">i0</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">i1</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">i2</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">i3</span> <span class="punctuation">)</span>
  <span class="punctuation">{</span>
    <span class="keyword">return</span> <span class="name">i0</span> <span class="operator">*</span> <span class="name">N3</span> <span class="operator">*</span> <span class="name">N2</span> <span class="operator">*</span> <span class="name">N1</span> <span class="comment single">// stride == N3 * N2 * N1
</span>         <span class="operator">+</span> <span class="name">i1</span> <span class="operator">*</span> <span class="name">N3</span> <span class="operator">*</span> <span class="name">N2</span>      <span class="comment single">// stride == N3 * N2
</span>         <span class="operator">+</span> <span class="name">i2</span> <span class="operator">*</span> <span class="name">N3</span>           <span class="comment single">// stride == N3
</span>         <span class="operator">+</span> <span class="name">i3</span> <span class="punctuation">;</span>              <span class="comment single">// stride == 1
</span>  <span class="punctuation">}</span>
</pre>
<!--  -->
<p>An initial set of layout properties are
<strong>layout_right</strong>, <strong>layout_left</strong>, <strong>layout_order</strong>,
and <strong>layout_stride</strong>,</p>
<blockquote>
<div class="line-block">
<div class="line">namespace std {</div>
<div class="line">namespace experimental {</div>
<div class="line">namespace array_property {</div>
<div class="line-block">
<div class="line">struct layout_right ;</div>
<div class="line">struct layout_left ;</div>
<div class="line">template&lt; unsigned ... &gt; struct layout_order ;</div>
<div class="line">struct layout_stride ;</div>
</div>
<div class="line">}}}</div>
</div>
</blockquote>
<pre class="code c++ literal-block">
<span class="keyword">typedef</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">array_property</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</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">3</span><span class="operator">&gt;</span> <span class="operator">&gt;</span> <span class="name">array_native</span> <span class="punctuation">;</span>

<span class="keyword">typedef</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">array_property</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</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">3</span><span class="operator">&gt;</span>
                       <span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">layout_right</span> <span class="operator">&gt;</span> <span class="name">array_right</span> <span class="punctuation">;</span>

<span class="keyword">typedef</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">array_property</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</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">3</span><span class="operator">&gt;</span>
                       <span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">layout_left</span> <span class="operator">&gt;</span>  <span class="name">array_left</span> <span class="punctuation">;</span>

<span class="name">assert</span><span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">is_same</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">array_native</span><span class="operator">::</span><span class="name">layout</span> <span class="punctuation">,</span> <span class="keyword type">void</span> <span class="operator">&gt;::</span><span class="name">value</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">is_same</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">array_right</span> <span class="operator">::</span><span class="name">layout</span> <span class="punctuation">,</span>
                      <span class="name">array_property</span><span class="operator">::</span><span class="name">layout_right</span> <span class="operator">&gt;::</span><span class="name">value</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">is_same</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">array_left</span>  <span class="operator">::</span><span class="name">layout</span> <span class="punctuation">,</span>
                      <span class="name">array_property</span><span class="operator">::</span><span class="name">layout_left</span> <span class="operator">&gt;::</span><span class="name">value</span> <span class="punctuation">);</span>

<span class="name">assert</span><span class="punctuation">(</span> <span class="name">array_native</span><span class="operator">::</span><span class="name">is_regular</span><span class="operator">::</span><span class="name">value</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">array_right</span> <span class="operator">::</span><span class="name">is_regular</span><span class="operator">::</span><span class="name">value</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">array_left</span>  <span class="operator">::</span><span class="name">is_regular</span><span class="operator">::</span><span class="name">value</span> <span class="punctuation">);</span>
</pre>
<!--  -->
<p>A <strong>void</strong> (<em>a.k.a.</em>, default or native) mapping is regular and bijective with
strides increasing from increasing from right most to left most dimension.
A <strong>layout_right</strong> mapping is regular and injective (may have padding) with
strides increasing from right most to left most dimension.
A <strong>layout_left</strong> mapping is regular and injective (may have padding) with
strides increasing from left most to right most dimension.
A <strong>layout_order</strong> mapping is regular and injective (may have padding)
with stride ordering defined by the template parameter pack.
A <strong>layout_stride</strong> mapping is regular; however, it might
not be injective or surjective.</p>
<pre class="code c++ literal-block">
<span class="comment single">// The right and left layout mapping of a rank-four
// multidimensional array could be is as if implemented
// as follows.  Note that padding is allowed but not required.
</span>
<span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword type">size_t</span> <span class="name">N0</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N1</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N2</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N4</span> <span class="operator">&gt;</span>
<span class="keyword type">size_t</span> <span class="name">right_mapping</span><span class="punctuation">(</span> <span class="keyword type">size_t</span> <span class="name">i0</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">i1</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">i2</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">i3</span> <span class="punctuation">)</span>
  <span class="punctuation">{</span>
    <span class="keyword">const</span> <span class="keyword type">size_t</span> <span class="name">S3</span> <span class="operator">=</span> <span class="comment single">// stride of dimension 3
</span>    <span class="keyword">const</span> <span class="keyword type">size_t</span> <span class="name">P3</span> <span class="operator">=</span> <span class="comment single">// padding of dimension 3
</span>    <span class="keyword">const</span> <span class="keyword type">size_t</span> <span class="name">P2</span> <span class="operator">=</span> <span class="comment single">// padding of dimension 2
</span>    <span class="keyword">const</span> <span class="keyword type">size_t</span> <span class="name">P1</span> <span class="operator">=</span> <span class="comment single">// padding of dimension 1
</span>    <span class="keyword">return</span> <span class="name">i0</span> <span class="operator">*</span> <span class="name">S3</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P3</span> <span class="operator">+</span> <span class="name">N3</span> <span class="punctuation">)</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P2</span> <span class="operator">+</span> <span class="name">N2</span> <span class="punctuation">)</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P1</span> <span class="operator">+</span> <span class="name">N1</span> <span class="punctuation">)</span>
         <span class="operator">+</span> <span class="name">i1</span> <span class="operator">*</span> <span class="name">S3</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P3</span> <span class="operator">+</span> <span class="name">N3</span> <span class="punctuation">)</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P2</span> <span class="operator">+</span> <span class="name">N2</span> <span class="punctuation">)</span>
         <span class="operator">+</span> <span class="name">i2</span> <span class="operator">*</span> <span class="name">S3</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P3</span> <span class="operator">+</span> <span class="name">N3</span> <span class="punctuation">)</span>
         <span class="operator">+</span> <span class="name">i3</span> <span class="operator">*</span> <span class="name">S3</span> <span class="punctuation">;</span>
  <span class="punctuation">}</span>

<span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword type">size_t</span> <span class="name">N0</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N1</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N2</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N4</span> <span class="operator">&gt;</span>
<span class="keyword type">size_t</span> <span class="name">left_mapping</span><span class="punctuation">(</span> <span class="keyword type">size_t</span> <span class="name">i0</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">i1</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">i2</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">i3</span> <span class="punctuation">)</span>
  <span class="punctuation">{</span>
    <span class="keyword">const</span> <span class="keyword type">size_t</span> <span class="name">S0</span> <span class="operator">=</span> <span class="comment single">// stride of dimension 0
</span>    <span class="keyword">const</span> <span class="keyword type">size_t</span> <span class="name">P0</span> <span class="operator">=</span> <span class="comment single">// padding of dimension 0
</span>    <span class="keyword">const</span> <span class="keyword type">size_t</span> <span class="name">P1</span> <span class="operator">=</span> <span class="comment single">// padding of dimension 1
</span>    <span class="keyword">const</span> <span class="keyword type">size_t</span> <span class="name">P2</span> <span class="operator">=</span> <span class="comment single">// padding of dimension 2
</span>    <span class="keyword">return</span> <span class="name">i0</span> <span class="operator">*</span> <span class="name">S0</span>
         <span class="operator">+</span> <span class="name">i1</span> <span class="operator">*</span> <span class="name">S0</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P0</span> <span class="operator">+</span> <span class="name">N0</span> <span class="punctuation">)</span>
         <span class="operator">+</span> <span class="name">i2</span> <span class="operator">*</span> <span class="name">S0</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P0</span> <span class="operator">+</span> <span class="name">N0</span> <span class="punctuation">)</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P1</span> <span class="operator">+</span> <span class="name">N1</span> <span class="punctuation">)</span>
         <span class="operator">+</span> <span class="name">i3</span> <span class="operator">*</span> <span class="name">S0</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P0</span> <span class="operator">+</span> <span class="name">N0</span> <span class="punctuation">)</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P1</span> <span class="operator">+</span> <span class="name">N1</span> <span class="punctuation">)</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">P2</span> <span class="operator">+</span> <span class="name">N2</span> <span class="punctuation">);</span>
  <span class="punctuation">}</span>
</pre>
<!--  -->
</div>
<div class="section" id="array-reference-properties-extensible-layout-polymorphism">
<h1>9&nbsp;&nbsp;&nbsp;Array Reference Properties: Extensible Layout Polymorphism</h1>
<p>The <strong>array_ref</strong> is intended to be extensible such that a user may supply
a customized layout mapping.
A user supplied customized layout mapping will be required to conform
to a specified interface; <em>a.k.a.</em>, a C++ Concept.
Details of this extension point will be included in a subsequent
proposal.
Our current extensibility strategy is for
a user supplied layout property to contain an offset mapping
as illustrated below.</p>
<pre class="code c++ literal-block">
<span class="keyword">struct</span> <span class="name">layout_tile_left</span> <span class="punctuation">{</span>
  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">Dimension</span> <span class="operator">&gt;</span> <span class="keyword">struct</span> <span class="name">offset</span> <span class="punctuation">;</span>
<span class="punctuation">};</span>
</pre>
<!--  -->
<p><em>Motivation:</em> An important customized layout mapping is hierarchical tiling.
This kind of layout mapping is used in dense linear algebra matrices and
computations on Cartesian grids to improve the spatial locality
of array entries.
These mappings are bijective but are not regular.
Computations on such multidimensional arrays typically iterate
through tiles as <em>subarray</em> of the array.</p>
<pre class="code c++ literal-block">
<span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword type">size_t</span> <span class="name">N0</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N1</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">N2</span> <span class="operator">&gt;</span>
<span class="keyword type">size_t</span> <span class="name">tiling_left_mapping</span><span class="punctuation">(</span> <span class="keyword type">size_t</span> <span class="name">i0</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">i1</span> <span class="punctuation">,</span> <span class="keyword type">size_t</span> <span class="name">i2</span> <span class="punctuation">)</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">T</span> <span class="operator">=</span> <span class="comment single">// cube tile size
</span>  <span class="keyword">constexpr</span> <span class="keyword type">size_t</span> <span class="name">T0</span> <span class="operator">=</span> <span class="punctuation">(</span> <span class="name">N0</span> <span class="operator">+</span> <span class="name">T</span> <span class="operator">-</span> <span class="literal number integer">1</span> <span class="punctuation">)</span> <span class="operator">/</span> <span class="name">T</span> <span class="punctuation">;</span> <span class="comment single">// tiles in dimension 0
</span>  <span class="keyword">constexpr</span> <span class="keyword type">size_t</span> <span class="name">T1</span> <span class="operator">=</span> <span class="punctuation">(</span> <span class="name">N1</span> <span class="operator">+</span> <span class="name">T</span> <span class="operator">-</span> <span class="literal number integer">1</span> <span class="punctuation">)</span> <span class="operator">/</span> <span class="name">T</span> <span class="punctuation">;</span> <span class="comment single">// tiles in dimension 1
</span>  <span class="keyword">constexpr</span> <span class="keyword type">size_t</span> <span class="name">T2</span> <span class="operator">=</span> <span class="punctuation">(</span> <span class="name">N2</span> <span class="operator">+</span> <span class="name">T</span> <span class="operator">-</span> <span class="literal number integer">1</span> <span class="punctuation">)</span> <span class="operator">/</span> <span class="name">T</span> <span class="punctuation">;</span> <span class="comment single">// tiles in dimension 2
</span>
  <span class="comment single">// offset within tile + offset to tile
</span>  <span class="keyword">return</span> <span class="punctuation">(</span> <span class="name">i0</span> <span class="operator">%</span> <span class="name">T</span> <span class="punctuation">)</span> <span class="operator">+</span> <span class="name">T</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">i1</span> <span class="operator">%</span> <span class="name">T</span> <span class="punctuation">)</span> <span class="operator">+</span> <span class="name">T</span> <span class="operator">*</span> <span class="name">T</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">i2</span> <span class="operator">%</span> <span class="name">T</span> <span class="punctuation">)</span>
       <span class="operator">+</span> <span class="name">T</span> <span class="operator">*</span> <span class="name">T</span> <span class="operator">*</span> <span class="name">T</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="punctuation">(</span> <span class="name">i0</span> <span class="operator">/</span> <span class="name">T</span> <span class="punctuation">)</span> <span class="operator">+</span> <span class="name">T0</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="punctuation">(</span> <span class="name">i1</span> <span class="operator">/</span> <span class="name">T</span> <span class="punctuation">)</span> <span class="operator">+</span> <span class="name">T1</span> <span class="operator">*</span> <span class="punctuation">(</span> <span class="name">i2</span> <span class="operator">/</span> <span class="name">T</span> <span class="punctuation">)</span> <span class="punctuation">)</span> <span class="punctuation">);</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
<p>Note that a tiled layout mapping is irregular and if padding is
required to align with tile boundarries then the span will exceed the size.
A customized layout mapping will have slightly different requirements
depending on whether the layout is regular or irregular.</p>
</div>
<div class="section" id="array-reference-properties-flexibility-and-extensibility">
<h1>10&nbsp;&nbsp;&nbsp;Array Reference Properties: Flexibility and Extensibility</h1>
<p>One or more array properties of <strong>void</strong> are acceptable and have no effect.
This allows user code to define a template argument list of potential
array properties and then enable/disable a particular property
by conditionally setting it to <strong>void</strong>.  For example:</p>
<pre class="code c++ literal-block">
<span class="keyword">using</span> <span class="name">layout</span> <span class="operator">=</span> <span class="name">std</span><span class="operator">::</span><span class="name">conditional</span><span class="operator">&lt;</span>
    <span class="name">ALLOW_PADDING</span> <span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">layout_right</span> <span class="punctuation">,</span> <span class="keyword type">void</span>
<span class="operator">&gt;::</span><span class="name">type</span> <span class="punctuation">;</span>

<span class="comment single">// If ALLOW_PADDING then use layout_right else use native layout
</span><span class="keyword">typedef</span> <span class="name">array</span><span class="operator">&lt;</span> <span class="keyword type">int</span> <span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</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">3</span><span class="operator">&gt;</span> <span class="punctuation">,</span> <span class="name">layout</span> <span class="operator">&gt;</span> <span class="name">MyType</span> <span class="punctuation">;</span>
</pre>
<!--  -->
</div>
<div class="section" id="specification-with-simple-array-reference-properties">
<h1>11&nbsp;&nbsp;&nbsp;Specification with Simple Array Reference Properties</h1>
<p>Simple array properties include the array layout and if necessary
a <strong>array_property::dimension</strong> type for arrays with multiple implicit dimensions.
Array reference properties are provided through a variadic template to
support extensibility of the array reference.
Possible additional properties include array bounds checking,
atomic access to members, memory space within a heterogeneous
memory architecture, and user access pattern hints.</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">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">struct</span> <span class="name">array_ref</span> <span class="punctuation">{</span>
  <span class="comment single">//--------------------
</span>  <span class="comment single">// Types:
</span>
  <span class="comment single">// Types are implementation and Properties dependent.
</span>  <span class="comment single">// The following type implementation are normative
</span>  <span class="comment single">// with respect to empty Properties.
</span>
  <span class="keyword">using</span> <span class="name">value_type</span> <span class="operator">=</span> <span class="keyword">typename</span> <span class="name">std</span><span class="operator">::</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">reference</span>  <span class="operator">=</span> <span class="name">value_type</span> <span class="operator">&amp;</span> <span class="punctuation">;</span> <span class="comment single">// Typical type, but implementation defined
</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="comment single">// Typical type, but implementation defined
</span>  <span class="keyword">using</span> <span class="name">size_type</span>  <span class="operator">=</span> <span class="keyword type">size_t</span> <span class="punctuation">;</span> <span class="comment single">// Typical type, but implementation defined
</span>
  <span class="keyword">using</span> <span class="name">layout</span> <span class="operator">=</span> <span class="operator">*</span><span class="name">array</span> <span class="name">layout</span> <span class="name">type</span><span class="operator">*</span> <span class="punctuation">;</span>

  <span class="comment single">//--------------------
</span>  <span class="comment single">// Domain index space properties:
</span>
  <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">rank</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">IntegralType</span> <span class="operator">&gt;</span>
  <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">extent</span><span class="punctuation">(</span> <span class="name">IntegralType</span> <span class="name">index</span> <span class="punctuation">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>

  <span class="comment single">// Cardinality of index space; i.e., product of extents
</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">//--------------------
</span>  <span class="comment single">// Layout mapping properties:
</span>
  <span class="keyword">static</span> <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_regular</span><span class="punctuation">()</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>

  <span class="comment single">// If the layout mapping is regular then return the
</span>  <span class="comment single">// distance between members when index \# is increased by one.
</span>  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">IntegralType</span> <span class="operator">&gt;</span>
  <span class="keyword">constexpr</span> <span class="name">size_type</span> <span class="name">stride</span><span class="punctuation">(</span> <span class="name">IntegralType</span> <span class="name">index</span> <span class="punctuation">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>

  <span class="comment single">// Span covering the members
</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="comment single">// Span of an array with regular layout if it
</span>  <span class="comment single">// is constructed with the given implicit dimensions.
</span>  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="punctuation">...</span> <span class="name">IntegralArgs</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">span</span><span class="punctuation">(</span> <span class="name">IntegralArgs</span> <span class="punctuation">...</span> <span class="name">implicit_dims</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

  <span class="comment single">// Pointer to member memory
</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="comment single">//--------------------
</span>  <span class="comment single">// Member access
</span>
  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="punctuation">...</span> <span class="name">IntegralArgs</span> <span class="operator">&gt;</span>
  <span class="name">reference</span> <span class="keyword">operator</span><span class="punctuation">()(</span> <span class="name">IntegralArgs</span> <span class="punctuation">...</span> <span class="name">indices</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">IntegralType</span> <span class="operator">&gt;</span>
  <span class="name">reference</span> <span class="keyword">operator</span><span class="punctuation">[](</span> <span class="name">IntegralType</span> <span class="name">index</span> <span class="punctuation">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>

  <span class="comment single">//--------------------
</span>  <span class="comment single">// Construct/move/copy/destroy:
</span>
  <span class="operator">~</span><span class="name">array_ref</span><span class="punctuation">()</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="name">rhs</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="operator">=</span> <span class="keyword">default</span> <span class="punctuation">;</span>
  <span class="keyword">constexpr</span> <span class="name">array_ref</span><span class="punctuation">(</span> <span class="keyword">const</span> <span class="name">array_ref</span> <span class="operator">&amp;</span> <span class="name">rhs</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="operator">=</span> <span class="keyword">default</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="name">rhs</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="operator">=</span> <span class="keyword">default</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="keyword">const</span> <span class="name">array_ref</span> <span class="operator">&amp;</span> <span class="name">rhs</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="operator">=</span> <span class="keyword">default</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">IntegralArgs</span> <span class="operator">&gt;</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">IntegralArgs</span> <span class="punctuation">...</span> <span class="name">implicit_dims</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">UProperties</span> <span class="operator">&gt;</span>
  <span class="keyword">constexpr</span> <span class="name">array_ref</span><span class="punctuation">(</span> <span class="keyword">const</span> <span class="name">array_ref</span><span class="operator">&lt;</span> <span class="name">UType</span> <span class="punctuation">,</span> <span class="name">UProperties</span> <span class="punctuation">...</span> <span class="operator">&gt;</span> <span class="operator">&amp;</span> <span class="name">rhs</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">UProperties</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="keyword">const</span> <span class="name">array_ref</span><span class="operator">&lt;</span> <span class="name">UType</span> <span class="punctuation">,</span> <span class="name">UProperties</span> <span class="punctuation">...</span> <span class="operator">&gt;</span> <span class="operator">&amp;</span> <span class="name">rhs</span> <span class="punctuation">)</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>
<span class="punctuation">};</span>

<span class="punctuation">}}</span>

<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">namespace</span> <span class="name">array_property</span> <span class="punctuation">{</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">template</span><span class="operator">&lt;</span> <span class="keyword type">unsigned</span> <span class="punctuation">...</span> <span class="operator">&gt;</span> <span class="name">layout_order</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">class</span> <span class="name class">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">class</span> <span class="name class">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="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">class</span> <span class="name class">T</span> <span class="operator">&gt;</span> <span class="keyword">struct</span> <span class="name">is_regular</span> <span class="punctuation">;</span>
<span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">class</span> <span class="name class">T</span> <span class="operator">&gt;</span> <span class="keyword">constexpr</span> <span class="keyword type">bool</span> <span class="name">is_regular_v</span> <span class="operator">=</span> <span class="name">is_regular</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="keyword">constexpr</span> <span class="keyword type">size_t</span> <span class="name">maximum_rank</span> <span class="operator">=</span> <span class="operator">/</span><span class="error">\</span><span class="operator">*</span> <span class="operator">&gt;=</span> <span class="literal number integer">10</span> <span class="error">\*/</span> <span class="punctuation">;</span>

<span class="comment single">// Specify mix of explicit and implict dimensions
</span><span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword type">size_t</span> <span class="punctuation">...</span> <span class="operator">&gt;</span>
<span class="keyword">struct</span> <span class="name">dimension</span> <span class="punctuation">{</span>
  <span class="comment single">//--------------------
</span>  <span class="comment single">// Types:
</span>
  <span class="keyword">using</span> <span class="name">value_type</span> <span class="operator">=</span> <span class="keyword type">size_t</span> <span class="punctuation">;</span> <span class="comment single">// Typical type, but implementation defined
</span>
  <span class="comment single">//--------------------
</span>  <span class="comment single">// Construct/move/copy/destroy:
</span>
  <span class="operator">~</span><span class="name">dimension</span><span class="punctuation">()</span> <span class="operator">=</span> <span class="keyword">default</span> <span class="punctuation">;</span>

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

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

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

  <span class="comment single">//--------------------
</span>  <span class="comment single">// Member access
</span>
  <span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">IntegralType</span> <span class="operator">&gt;</span>
  <span class="keyword">constexpr</span> <span class="name">value_type</span> <span class="keyword">operator</span><span class="punctuation">[](</span> <span class="name">IntegralType</span> <span class="name">dim</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><strong>Properties template parameter pack</strong></p>
<p>An array_ref is given properties
(such as <tt class="docutils literal">layout_left</tt>, <tt class="docutils literal">layout_right</tt>, and <tt class="docutils literal">layout_stride</tt>)
through the <tt class="docutils literal">Properties</tt> template parameter pack.</p>
<blockquote>
Effects: A <tt class="docutils literal">void</tt> member in a <tt class="docutils literal">Properties</tt> pack is ignored.</blockquote>
<p><strong>Layout Properties</strong></p>
<p>If a layout property does not appear in the <tt class="docutils literal">Properties</tt> pack
the layout is <tt class="docutils literal">void</tt>.</p>
<blockquote>
<p>Requires:  is_layout_v&lt; void &gt; == true,
is_layout_v&lt; layout_right &gt; == true,
is_layout_v&lt; layout_left &gt; == true,
is_layout_v&lt; layout_stride &gt; == true, and
is_layout_v&lt; layout_order&lt;...&gt; &gt; == true.</p>
<p>Requires:  is_regular_v&lt; void &gt; == true,
is_regular_v&lt; layout_right &gt; == true,
is_regular_v&lt; layout_left &gt; == true,
is_regular_v&lt; layout_stride &gt; == true, and
is_regular_v&lt; layout_order&lt;...&gt; &gt; == true.</p>
<p>Requires:  At most one member of the <tt class="docutils literal">Properties</tt> pack
is a layout property.</p>
<p>Effects:  <tt class="docutils literal"><span class="pre">array_ref::layout</span></tt> is the layout property
given in the <tt class="docutils literal">Properties</tt> pack or <tt class="docutils literal">void</tt> if no
layout property is given.</p>
<p>Effects:  Given a one of these regular layouts an
array_ref strides and layout mapping conform to the following.</p>
</blockquote>
<pre class="code c++ literal-block">
<span class="keyword">using</span> <span class="name">a_type</span> <span class="operator">=</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">a_type</span> <span class="name function">a</span><span class="punctuation">(</span> <span class="name">ptr</span> <span class="punctuation">,</span> <span class="name">dims</span><span class="punctuation">...</span> <span class="punctuation">);</span>

<span class="keyword">if</span> <span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">is_lvalue_reference_v</span><span class="operator">&lt;</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">reference</span> <span class="operator">&gt;</span> <span class="operator">&amp;&amp;</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">is_regular</span>
   <span class="operator">&amp;&amp;</span> <span class="literal number integer">0</span> <span class="operator">&lt;=</span> <span class="name">i</span> <span class="operator">&amp;&amp;</span> <span class="name">i</span> <span class="operator">&lt;=</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">rank</span><span class="punctuation">()</span> <span class="operator">&amp;&amp;</span> <span class="literal number integer">0</span> <span class="operator">&lt;=</span> <span class="name">ji</span> <span class="operator">&amp;&amp;</span> <span class="name">ji</span> <span class="operator">&lt;</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">extent</span><span class="punctuation">(</span><span class="name">i</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="name">assert</span><span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">distance</span><span class="punctuation">(</span> <span class="operator">&amp;</span> <span class="name">a</span><span class="punctuation">(</span><span class="name">j0</span><span class="punctuation">,...,</span><span class="name">ji</span><span class="punctuation">,...)</span> <span class="punctuation">,</span> <span class="operator">&amp;</span> <span class="name">a</span><span class="punctuation">(</span><span class="name">j0</span><span class="punctuation">,...,</span><span class="name">ji</span><span class="operator">+</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="name">stride</span><span class="punctuation">(</span><span class="name">i</span><span class="punctuation">)</span> <span class="punctuation">);</span>
<span class="punctuation">}</span>

<span class="keyword">if</span> <span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">is_same_v</span><span class="operator">&lt;</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">layout</span> <span class="punctuation">,</span> <span class="keyword type">void</span> <span class="operator">&gt;</span> <span class="punctuation">)</span> <span class="punctuation">{</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">is_regular</span> <span class="punctuation">);</span>
  <span class="keyword">if</span> <span class="punctuation">(</span> <span class="name">i</span> <span class="operator">+</span> <span class="literal number integer">1</span> <span class="operator">==</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">rank</span><span class="punctuation">()</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">stride</span><span class="punctuation">(</span><span class="name">i</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="literal number integer">1</span> <span class="punctuation">);</span>
  <span class="keyword">else</span> <span class="name function">if</span> <span class="punctuation">(</span> <span class="literal number integer">0</span> <span class="operator">&lt;</span> <span class="name">i</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">stride</span><span class="punctuation">(</span><span class="name">i</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">stride</span><span class="punctuation">(</span><span class="name">i</span><span class="operator">+</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="name">dimension</span><span class="punctuation">(</span><span class="name">i</span><span class="operator">+</span><span class="literal number integer">1</span><span class="punctuation">)</span> <span class="punctuation">);</span>
<span class="punctuation">}</span>
<span class="keyword">else</span> <span class="keyword">if</span> <span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">is_same_v</span><span class="operator">&lt;</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">layout</span> <span class="punctuation">,</span> <span class="name">layout_right</span> <span class="operator">&gt;</span> <span class="punctuation">)</span> <span class="punctuation">{</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">is_regular</span> <span class="punctuation">)</span>
  <span class="keyword">if</span> <span class="punctuation">(</span> <span class="name">i</span> <span class="operator">+</span> <span class="literal number integer">1</span> <span class="operator">==</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">rank</span><span class="punctuation">()</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">stride</span><span class="punctuation">(</span><span class="name">i</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="literal number integer">1</span> <span class="punctuation">);</span>
  <span class="keyword">else</span> <span class="name function">if</span> <span class="punctuation">(</span> <span class="literal number integer">0</span> <span class="operator">&lt;</span> <span class="name">i</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">stride</span><span class="punctuation">(</span><span class="name">i</span><span class="punctuation">)</span> <span class="operator">&gt;=</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">stride</span><span class="punctuation">(</span><span class="name">i</span><span class="operator">+</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="name">dimension</span><span class="punctuation">(</span><span class="name">i</span><span class="operator">+</span><span class="literal number integer">1</span><span class="punctuation">)</span> <span class="punctuation">);</span>
<span class="punctuation">}</span>
<span class="keyword">else</span> <span class="keyword">if</span> <span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">is_same_v</span><span class="operator">&lt;</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">layout</span> <span class="punctuation">,</span> <span class="name">layout_left</span> <span class="operator">&gt;</span> <span class="punctuation">)</span> <span class="punctuation">{</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">is_regular</span> <span class="punctuation">)</span>
  <span class="keyword">if</span> <span class="punctuation">(</span> <span class="name">i</span> <span class="operator">==</span> <span class="literal number integer">0</span> <span class="operator">&amp;&amp;</span> <span class="literal number integer">0</span> <span class="operator">&lt;</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">rank</span><span class="punctuation">()</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">stride</span><span class="punctuation">(</span><span class="name">i</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="literal number integer">1</span> <span class="punctuation">);</span>
  <span class="keyword">else</span> <span class="name function">if</span> <span class="punctuation">(</span> <span class="name">i</span> <span class="operator">&lt;</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">rank</span><span class="punctuation">()</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">stride</span><span class="punctuation">(</span><span class="name">i</span><span class="punctuation">)</span> <span class="operator">&gt;=</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">stride</span><span class="punctuation">(</span><span class="name">i</span><span class="operator">-</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="name">dimension</span><span class="punctuation">(</span><span class="name">i</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">)</span> <span class="punctuation">);</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
<p><strong>array_property::layout_order&lt; unsigned ... order &gt;</strong></p>
<blockquote>
<p>Requires: The members of <tt class="docutils literal">order</tt> are the integers [ 0 , <tt class="docutils literal"><span class="pre">sizeof...(order)</span></tt> ).</p>
<p>Requires: When an <tt class="docutils literal">array_ref</tt> has a <tt class="docutils literal">layout_order</tt> property
then <tt class="docutils literal">rank() == <span class="pre">sizeof...(order)</span></tt>.</p>
<p>Effects: The <tt class="docutils literal">order</tt> pack specifies the ordering relationship of
dimensions in the mapping.</p>
</blockquote>
<pre class="code c++ literal-block">
<span class="keyword">constexpr</span> <span class="keyword type">unsigned</span> <span class="name">i0</span> <span class="operator">=</span> <span class="comment multiline">/* [0, 3) */</span> <span class="punctuation">;</span>
<span class="keyword">constexpr</span> <span class="keyword type">unsigned</span> <span class="name">i1</span> <span class="operator">=</span> <span class="comment multiline">/* [0, 3)  and  != i1 */</span> <span class="punctuation">;</span>
<span class="keyword">constexpr</span> <span class="keyword type">unsigned</span> <span class="name">i2</span> <span class="operator">=</span> <span class="comment multiline">/* [0, 3)  and  != i1  and  != i2 */</span> <span class="punctuation">;</span>

<span class="keyword">using</span> <span class="name">a_type</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">3</span><span class="punctuation">][</span><span class="literal number integer">4</span><span class="punctuation">]</span> <span class="punctuation">,</span> <span class="name">layout_order</span><span class="operator">&lt;</span> <span class="name">i0</span> <span class="punctuation">,</span> <span class="name">i1</span> <span class="punctuation">,</span> <span class="name">i2</span> <span class="operator">&gt;</span> <span class="operator">&gt;</span> <span class="punctuation">;</span>

<span class="name">assert</span><span class="punctuation">(</span> <span class="name">a_type</span><span class="operator">::</span><span class="name">is_regular</span> <span class="punctuation">);</span>

<span class="name">a_type</span> <span class="name function">A</span><span class="punctuation">(</span> <span class="name">ptr</span> <span class="punctuation">,</span> <span class="name">dims</span><span class="punctuation">...</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">stride</span><span class="punctuation">(</span><span class="name">i0</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="literal number integer">1</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">stride</span><span class="punctuation">(</span><span class="name">i1</span><span class="punctuation">)</span> <span class="operator">&gt;=</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">stride</span><span class="punctuation">(</span><span class="name">i0</span><span class="punctuation">)</span> <span class="operator">*</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">extent</span><span class="punctuation">(</span><span class="name">i0</span><span class="punctuation">)</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">stride</span><span class="punctuation">(</span><span class="name">i2</span><span class="punctuation">)</span> <span class="operator">&gt;=</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">stride</span><span class="punctuation">(</span><span class="name">i1</span><span class="punctuation">)</span> <span class="operator">*</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">extent</span><span class="punctuation">(</span><span class="name">i1</span><span class="punctuation">)</span> <span class="punctuation">);</span>
</pre>
<!--  -->
<p><strong>Dimension Specification</strong></p>
<p>The dimension specification of an array_ref may be given
through the <tt class="docutils literal">DataType</tt> template argument or through one of the
<tt class="docutils literal">Properties</tt> template arguments. For example, the dimension
specification for an array_ref with leading implicit dimension
and a second explicit dimension is specified by either of the
following declarations.</p>
<pre class="code c++ literal-block">
<span class="name">array_ref</span><span class="operator">&lt;</span> <span class="name">T</span> <span class="punctuation">[][</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">&gt;</span>
<span class="name">array_ref</span><span class="operator">&lt;</span> <span class="name">T</span> <span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</span> <span class="literal number integer">0</span> <span class="punctuation">,</span> <span class="literal number integer">3</span> <span class="operator">&gt;</span> <span class="operator">&gt;</span>
</pre>
<!--  -->
<blockquote>
<p>Remark: When a dimension specification is part of the <tt class="docutils literal">DataType</tt>
the specification is limited by the valid
<em>multidimensional array type</em> declaration syntax (n4567 8.3.4.p3).
If a
<a class="reference internal" href="#relaxation-of-the-current-multidimensional-array-type-declaration">relaxation of the current multidimensional array type declaration</a>
were made the <tt class="docutils literal"><span class="pre">array_property::dimension&lt;</span> ... &gt;</tt> would be unnecessary and
eliminated from this proposal.</p>
<p>Requires: If <tt class="docutils literal"><span class="pre">std::extent&lt;</span> DataType <span class="pre">&gt;::value</span> == 0</tt> then at most
one <tt class="docutils literal">Properties</tt> template argument may be
<tt class="docutils literal"><span class="pre">array_property::dimension&lt;</span> ... &gt;</tt>.</p>
<p>Effects: When the dimension specification is given
as part of the <tt class="docutils literal">DataType</tt> then
an explicit dimension is specified by each <tt class="docutils literal">[N]</tt>,
an implicit dimension is specified by each <tt class="docutils literal">[]</tt>,
<tt class="docutils literal">rank() == <span class="pre">std::rank&lt;</span> DataType <span class="pre">&gt;::value</span></tt>, and
<tt class="docutils literal">extent(i) == <span class="pre">std::extent&lt;</span> DataType , i <span class="pre">&gt;::value</span></tt>
for <tt class="docutils literal">i &lt; rank()</tt> and default constructed array_ref.</p>
<p>Effects: When the dimension specification is given via
<tt class="docutils literal"><span class="pre">array_property::dimension&lt;</span> N0, N1 , ... &gt;</tt> then
<tt class="docutils literal">0 &lt;= Nj</tt> for all j,
an explicit dimensions is specified by <tt class="docutils literal">0 &lt; Nj</tt>
an implicit dimensions is specified by <tt class="docutils literal">0 == Nj</tt>
<tt class="docutils literal">rank() ==</tt> number of arguments, and
<tt class="docutils literal">extent(j) == Nj</tt> for <tt class="docutils literal">j &lt; rank()</tt> and
default constructed array_ref.</p>
<p>Requires: <tt class="docutils literal">10 &lt;= maximum_rank</tt></p>
<p>Effect: An implementation supports array references up to maximum_rank.</p>
<p>Remark: An array_ref implementation may use rank-specific optimizations.
As such an indefinite maximum rank may be impractical.  An implementation
must support at least this rank.</p>
</blockquote>
<p><strong>using value_type = typename std::remove_all_extents&lt; DataType &gt;::type</strong></p>
<blockquote>
The type of each element of the referenced array.</blockquote>
<p><strong>using reference =</strong></p>
<blockquote>
The type returned by the member access operator.
Typically this will be <tt class="docutils literal">value_type &amp;</tt>.
[Note: The reference type may be a proxy depending upon the <tt class="docutils literal">Properties</tt>.
For example, if a property indicates that all member references
are to be atomic then the reference type would be a
proxy conforming to <em>atomic-view-concept</em> introduced in paper P0019.
- end note]</blockquote>
<p><strong>using pointer =</strong></p>
<blockquote>
The input type to a wrapping constructor.</blockquote>
<p><strong>using size_type =</strong></p>
<blockquote>
The type that counts the number of elements in the referenced array.</blockquote>
<p><strong>using layout=</strong></p>
<blockquote>
The layout type property that defaults to <tt class="docutils literal">void</tt>.</blockquote>
<p><strong>static constexpr size_type rank() noexcept</strong></p>
<blockquote>
Returns: The rank of the referenced array.</blockquote>
<p><strong>template&lt; typename IntegralType &gt;</strong></p>
<p><strong>constexpr size_type extent( IntegralType index ) const noexcept</strong></p>
<blockquote>
<p>Requires: std::is_integral&lt; IntegralType &gt;::value</p>
<p>Returns: When <tt class="docutils literal">r &lt; rank()</tt> the exent of dimension, otherwise 1.
A default constructed array_ref will have <tt class="docutils literal">extent(r) == 0</tt>
for all implicit dimensions.
The return value of an explicit dimension queried with a
literal input value must be &quot;constexpr&quot; observable.</p>
</blockquote>
<p><strong>constexpr size_type size() const noexcept</strong></p>
<blockquote>
Returns: The product of the extents.</blockquote>
<p><strong>static constexpr bool is_regular() noexcept</strong></p>
<blockquote>
Returns: True if the layout mapping is regular; <em>i.e.</em>, if there
is a uniform stride between members when incrementing a particular
dereferencing index and holding all other indices fixed.</blockquote>
<p><strong>template&lt; typename IntegralType &gt;</strong></p>
<p><strong>constexpr size_type stride( IntegralType index ) const noexcept</strong></p>
<blockquote>
<p>Requires: std::is_integral&lt; IntegralType &gt;::value</p>
<p>Requires: is_regular()</p>
<p>Returns: When is_regular::value and <tt class="docutils literal">0 &lt;= r &lt; rank()</tt>
the distance between members when index <tt class="docutils literal">r</tt> is incremented by one,
otherwise 0.</p>
</blockquote>
<p><strong>constexpr size_type span() const noexcept</strong></p>
<blockquote>
<p>Returns:  A distance that is at least maximum distance between any two
members of the array plus one. All member of the array reside in the span
<tt class="docutils literal">[ data() , data() + span() )</tt>.</p>
<p>Remark: For a one-to-one layout mapping the span will equal the size.</p>
</blockquote>
<p><strong>template&lt; typename ... IntegralArgs &gt;</strong></p>
<p><strong>static constexpr size_type span( IntegralArgs ... implicit_dims ) noexcept</strong></p>
<blockquote>
<p>Requires: <tt class="docutils literal"><span class="pre">conjunction&lt;is_integral&lt;IntegralArgs&gt;::type...&gt;::value</span></tt></p>
<p>Requires: All <tt class="docutils literal">implicit_dims</tt> parameters are non-negative.</p>
<p>Returns: The span of the array reference if it were constructed with the implicit dimensions.</p>
</blockquote>
<p><strong>constexpr pointer data() const noexcept</strong></p>
<blockquote>
<p>Requires: All members are in the range <tt class="docutils literal">[ data() , data() + span() )</tt>.</p>
<p>Returns: Pointer to the member with the minimum location.</p>
</blockquote>
<p><strong>template&lt; typename ... IntegralArgs &gt;</strong></p>
<p><strong>reference operator()( IntegralArgs ... indices ) const noexcept</strong></p>
<blockquote>
<p>Requires: <tt class="docutils literal"><span class="pre">conjunction&lt;is_integral&lt;IntegralArgs&gt;::type...&gt;::value</span></tt></p>
<p>Requires: All <tt class="docutils literal">indices</tt> parameters are non-negative.</p>
<p>Requires: <tt class="docutils literal">rank() == <span class="pre">sizeof...(IntegralArgs)</span></tt></p>
<p>Requires: The ith argument <em>indices[i]*</em> is in bounds;
<em>indices[i]</em> <tt class="docutils literal">&lt; extent(i)</tt>.</p>
<p>Returns: A reference to the member referenced by the indices argument.</p>
<p>Remark: An implementation may have rank-specific overloads to better
enable optimization of the member access operator.</p>
</blockquote>
<pre class="code c++ literal-block">
<span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">ArrayRefType</span><span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">I0</span> <span class="operator">&gt;</span>
<span class="keyword">typename</span> <span class="name">std</span><span class="operator">::</span><span class="name">enable_if</span><span class="operator">&lt;</span> <span class="name">ArrayRefType</span><span class="operator">::</span><span class="name">rank</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">1</span>
                       <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">ArrayRefType</span><span class="operator">::</span><span class="name">reference</span> <span class="operator">&gt;::</span><span class="name">type</span>
<span class="name">array_ref_index</span><span class="punctuation">(</span> <span class="name">I0</span> <span class="name">i0</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">ArrayRefType</span><span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">I0</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">I1</span> <span class="operator">&gt;</span>
<span class="keyword">typename</span> <span class="name">std</span><span class="operator">::</span><span class="name">enable_if</span><span class="operator">&lt;</span> <span class="name">ArrayRefType</span><span class="operator">::</span><span class="name">rank</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">2</span>
                       <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">ArrayRefType</span><span class="operator">::</span><span class="name">reference</span> <span class="operator">&gt;::</span><span class="name">type</span>
<span class="name">array_ref_index</span><span class="punctuation">(</span> <span class="name">I0</span> <span class="name">i0</span> <span class="punctuation">,</span> <span class="name">I1</span> <span class="name">i1</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">ArrayRefType</span><span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">I0</span><span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">I1</span><span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">I2</span>
        <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="punctuation">...</span> <span class="name">IntegralArgs</span> <span class="operator">&gt;</span>
<span class="keyword">typename</span> <span class="name">std</span><span class="operator">::</span><span class="name">enable_if</span><span class="operator">&lt;</span> <span class="name">ArrayRefType</span><span class="operator">::</span><span class="name">rank</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="punctuation">(</span><span class="keyword">sizeof</span><span class="punctuation">...(</span><span class="name">IntegralArgs</span><span class="punctuation">)</span> <span class="operator">+</span> <span class="literal number integer">3</span><span class="punctuation">)</span>
                       <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">ArrayRefType</span><span class="operator">::</span><span class="name">reference</span> <span class="operator">&gt;::</span><span class="name">type</span>
<span class="name">array_ref_index</span><span class="punctuation">(</span> <span class="name">I0</span> <span class="name">i0</span><span class="punctuation">,</span> <span class="name">I1</span> <span class="name">i1</span><span class="punctuation">,</span> <span class="name">I2</span> <span class="name">i2</span><span class="punctuation">,</span> <span class="name">IntegralArgs</span> <span class="punctuation">...</span> <span class="name">indices</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">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">struct</span> <span class="name">array_ref</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">IntegralArgs</span> <span class="operator">&gt;</span>
   <span class="name">reference</span> <span class="keyword">operator</span><span class="punctuation">()(</span> <span class="name">IntegralArgs</span> <span class="punctuation">...</span> <span class="name">indices</span> <span class="punctuation">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="punctuation">{</span>
     <span class="keyword">return</span> <span class="name">array_ref_index</span><span class="operator">&lt;</span><span class="name">array_ref</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="name">indices</span><span class="punctuation">...);</span>
   <span class="punctuation">}</span>
<span class="punctuation">};</span>
</pre>
<!--  -->
<p><strong>template&lt; typename IntegralType &gt;</strong></p>
<p><strong>reference operator[]( IntegralType index ) const noexcept</strong></p>
<blockquote>
<p>Requires: rank() == 1</p>
<p>Requires: is_integral&lt; IntegralType &gt;::value</p>
<p>Requires: 0 &lt;= i &lt; extent(0)</p>
<p>Returns: Reference to member denoted by index <tt class="docutils literal">i</tt>.</p>
<p>Remark:  Provides compatibility with traditional rank-one array member reference.</p>
<p>Remark:  It is recommended that the rank and type requirements be enforced
by conditionally enabling the operator.</p>
</blockquote>
<pre class="code c++ literal-block">
<span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">IntegralType</span> <span class="operator">&gt;</span>
<span class="keyword">typename</span> <span class="name">std</span><span class="operator">::</span><span class="name">enable_if</span><span class="operator">&lt;</span>
    <span class="name">std</span><span class="operator">::</span><span class="name">is_integral</span><span class="operator">&lt;</span> <span class="name">IntegralType</span> <span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">&amp;&amp;</span> <span class="literal number integer">1</span> <span class="operator">==</span> <span class="name">rank</span><span class="punctuation">()</span> <span class="punctuation">,</span> <span class="name">reference</span>
<span class="operator">&gt;::</span><span class="name">type</span>
<span class="keyword">operator</span><span class="punctuation">[](</span> <span class="keyword">const</span> <span class="name">IntegralType</span> <span class="operator">&amp;</span> <span class="name">i</span> <span class="punctuation">)</span> <span class="keyword">const</span> <span class="keyword">noexcept</span> <span class="punctuation">;</span>
</pre>
<!--  -->
<p><strong>~array_ref()</strong></p>
<blockquote>
<p>Effect: Assigns <tt class="docutils literal">this</tt> to be a <em>null</em> array_ref.</p>
<p>Remark: There may be other <em>property</em> dependent effects.</p>
</blockquote>
<p><strong>constexpr array_ref() noexcept</strong></p>
<blockquote>
Effect: Construct a <em>null</em> array_ref with extent(i) == 0
for all implicit dimensions and data() == nullptr.</blockquote>
<p><strong>constexpr array_ref( const array_ref &amp; rhs ) noexcept = default</strong></p>
<blockquote>
<p>Effect: Construct a array_ref of the same array referenced by <tt class="docutils literal">rhs</tt>.</p>
<p>Remark: There may be other <em>property</em> dependent effects.</p>
</blockquote>
<p><strong>array_ref &amp; operator = ( const array_ref &amp; rhs ) noexcept = default</strong></p>
<blockquote>
<p>Effect: Assigns <tt class="docutils literal">this</tt> to array_ref the same array referenced  by <tt class="docutils literal">rhs</tt>.</p>
<p>Remark: There may be other <em>property</em> dependent effects.</p>
</blockquote>
<p><strong>constexpr array_ref( array_ref &amp;&amp; rhs ) noexcept = default</strong></p>
<blockquote>
<p>Effect: Construct a array_ref of the array referenced by <tt class="docutils literal">rhs</tt> and then <tt class="docutils literal">rhs</tt> is <em>null</em> array_ref.</p>
<p>Remark: There may be other <em>property</em> dependent effects.</p>
</blockquote>
<p><strong>array_ref &amp; operator = ( array_ref &amp;&amp; rhs ) noexcept = default</strong></p>
<blockquote>
<p>Effect: Assigns <tt class="docutils literal">this</tt> to array_ref the array referenced by <tt class="docutils literal">rhs</tt> then assigns <tt class="docutils literal">rhs</tt> to be a <em>null</em> array_ref.</p>
<p>Remark: There may be other <em>property</em> dependent effects.</p>
</blockquote>
<p><strong>template&lt; typename ... IntegralArgs &gt;</strong></p>
<p><strong>constexpr array_ref( pointer ptr , IntegralArgs ... implicit_dims ) noexcept</strong></p>
<blockquote>
<p>Requires: The input <tt class="docutils literal">ptr</tt> references memory <tt class="docutils literal">[ ptr , ptr + S )</tt>
where S = <tt class="docutils literal"><span class="pre">array_ref::span(args...)</span></tt>.</p>
<p>Effects: The <em>wrapping constructor</em> constructs a multidimensional array
reference of the given member memory
such that all data members are in the span <tt class="docutils literal">[ ptr , ptr + span() )</tt>.</p>
</blockquote>
<p><strong>template&lt; typename UType , typename ... UProperties &gt;</strong></p>
<p><strong>constexpr array_ref( const array_ref&lt; UType , UProperties ... &gt; &amp; rhs ) noexcept</strong></p>
<blockquote>
<p>Requires: This array_ref type is assignable to the <tt class="docutils literal">rhs</tt> array_ref type.
Assignability includes compatibility of the value type, dimensions, and properties.</p>
<p>Effect: Constructs a array_ref of the array referenced by <tt class="docutils literal">rhs</tt>.</p>
</blockquote>
<pre class="code c++ literal-block">
<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">3</span><span class="punctuation">]</span> <span class="operator">&gt;</span> <span class="name">x</span><span class="punctuation">(</span><span class="name">ptr</span><span class="punctuation">,</span> <span class="name">N0</span><span class="punctuation">);</span>

<span class="comment single">// OK: compatible const from non-const and implicit from explicit dimension
</span><span class="name">array_ref</span><span class="operator">&lt;</span> <span class="keyword">const</span> <span class="keyword type">int</span> <span class="punctuation">,</span> <span class="name">array_properties</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</span> <span class="literal number integer">0</span> <span class="punctuation">,</span> <span class="literal number integer">0</span> <span class="operator">&gt;</span> <span class="operator">&gt;</span> <span class="name">y</span><span class="punctuation">(</span><span class="name">x</span><span class="punctuation">);</span>

<span class="comment single">// Error: cannot assign non-const from const
</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">array_properties</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</span> <span class="literal number integer">0</span> <span class="punctuation">,</span> <span class="literal number integer">0</span> <span class="operator">&gt;</span> <span class="operator">&gt;</span> <span class="name">z</span><span class="punctuation">(</span><span class="name">y</span><span class="punctuation">);</span>
</pre>
<!--  -->
<p><strong>template&lt; typename UType , typename ... UProperties &gt;</strong></p>
<p><strong>array_ref &amp; operator = ( const array_ref&lt; UType , UProperties ... &gt; &amp; rhs ) noexcept</strong></p>
<blockquote>
<p>Requires: This array_ref type is assignable to the <tt class="docutils literal">rhs</tt> array_ref type.</p>
<p>Effect: Assigns <tt class="docutils literal">this</tt> to array_ref the array array_ref by <tt class="docutils literal">rhs</tt>.</p>
</blockquote>
</div>
<div class="section" id="assignability-of-array-references-of-non-identical-types">
<h1>12&nbsp;&nbsp;&nbsp;Assignability of Array References of Non-identical Types</h1>
<p>It is essential that array_ref of non-identical, compatible types be assignable.
For example:</p>
<pre class="code c++ literal-block">
<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">3</span><span class="punctuation">]</span> <span class="operator">&gt;</span> <span class="name">x</span><span class="punctuation">(</span><span class="name">ptr</span> <span class="punctuation">,</span> <span class="name">N0</span><span class="punctuation">);</span>

<span class="comment single">// valid assignment
</span><span class="name">array_ref</span><span class="operator">&lt;</span> <span class="keyword">const</span> <span class="keyword type">int</span> <span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</span> <span class="literal number integer">0</span> <span class="punctuation">,</span> <span class="literal number integer">0</span> <span class="operator">&gt;</span> <span class="operator">&gt;</span> <span class="name">y</span><span class="punctuation">(</span><span class="name">x</span><span class="punctuation">);</span>
</pre>
<!--  -->
<p>The 'std::is_assignable' meta-function must be partial specialized to
implement the array_ref assignability rules regarding value type, dimensions, and properties.</p>
<pre class="code c++ literal-block">
<span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">class</span> <span class="name class">Utype</span> <span class="punctuation">,</span> <span class="keyword">class</span> <span class="error">... </span><span class="name class">Uprop</span>
        <span class="punctuation">,</span> <span class="keyword">class</span> <span class="name class">Vtype</span> <span class="punctuation">,</span> <span class="keyword">class</span> <span class="error">... </span><span class="name class">Vprop</span> <span class="operator">&gt;</span>
<span class="keyword">struct</span> <span class="name">is_assignable</span><span class="operator">&lt;</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="punctuation">,</span> <span class="name">array_ref</span><span class="operator">&lt;</span> <span class="name">Vtype</span> <span class="punctuation">,</span> <span class="name">Vprop</span> <span class="punctuation">...</span> <span class="operator">&gt;</span> <span class="operator">&gt;</span>
  <span class="operator">:</span> <span class="keyword">public</span> <span class="name">integral_const</span><span class="operator">&lt;</span> <span class="keyword type">bool</span> <span class="punctuation">,</span>
      <span class="name">is_assignable</span><span class="operator">&lt;</span> <span class="keyword">typename</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="name">pointer</span>
                   <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">array_ref</span><span class="operator">&lt;</span> <span class="name">Vtype</span> <span class="punctuation">,</span> <span class="name">Vprop</span> <span class="punctuation">...</span> <span class="operator">&gt;::</span><span class="name">pointer</span>
                   <span class="operator">&gt;::</span><span class="name">value</span>
      <span class="operator">&amp;&amp;</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="name">rank</span><span class="punctuation">()</span> <span class="operator">==</span>
        <span class="name">array_ref</span><span class="operator">&lt;</span> <span class="name">Vtype</span> <span class="punctuation">,</span> <span class="name">Vprop</span> <span class="punctuation">...</span> <span class="operator">&gt;::</span><span class="name">rank</span><span class="punctuation">()</span> <span class="punctuation">)</span>
      <span class="operator">&amp;&amp;</span>
      <span class="punctuation">(</span>
        <span class="comment single">// Extent is either equal or implicit.
</span>        <span class="name">extent</span><span class="operator">&lt;</span><span class="name">Utype</span><span class="punctuation">,</span><span class="error">#</span><span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">==</span> <span class="name">extent</span><span class="operator">&lt;</span><span class="name">Vtype</span><span class="punctuation">,</span><span class="error">#</span><span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">||</span>
        <span class="name">extent</span><span class="operator">&lt;</span><span class="name">Utype</span><span class="punctuation">,</span><span class="error">#</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="operator">&amp;&amp;</span>
      <span class="comment single">// other possible conditions
</span>      <span class="operator">&gt;</span> <span class="punctuation">{}</span>
</pre>
<!--  -->
<p>Assignability extends beyond the <strong>cv</strong> qualification of the array_ref's data.
For example,</p>
<blockquote>
<ol class="arabic simple">
<li>Implicitly dimensioned array_ref are assignable from equal rank explicitly dimensioned array_ref,</li>
<li>Strided layout array_ref with implicit dimensions are assignable from equal rank array_ref with regular layout, or</li>
<li>A array_ref with an access intent property, such as <em>random</em> or <em>restrict</em> may be assigned from a array_ref without such a property.</li>
</ol>
</blockquote>
</div>
<div class="section" id="subarray-interface">
<h1>13&nbsp;&nbsp;&nbsp;Subarray Interface</h1>
<p>The capability to <strong>easily</strong> extract subarrays of an array,
or subarrays of subarrays, is essential for usability.
Non-trivial subarrays of regular arrays will often have <strong>layout_stride</strong>.</p>
<pre class="code c++ literal-block">
<span class="keyword">using</span> <span class="name">U</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">array_properties</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</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="operator">&gt;</span> <span class="operator">&gt;</span> <span class="punctuation">;</span>

<span class="name">U</span> <span class="name function">x</span><span class="punctuation">(</span><span class="name">buffer</span><span class="punctuation">,</span><span class="name">N0</span><span class="punctuation">,</span><span class="name">N1</span><span class="punctuation">,</span><span class="name">N2</span><span class="punctuation">);</span>

<span class="comment single">// Using std::pair&lt;int,int&gt; for an integral range
</span><span class="keyword">auto</span> <span class="name">y</span> <span class="operator">=</span> <span class="name">subarray</span><span class="punctuation">(</span> <span class="name">x</span> <span class="punctuation">,</span> <span class="name">std</span><span class="operator">::</span><span class="name">pair</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="punctuation">,</span><span class="keyword type">int</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">,</span><span class="name">N0</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">)</span> <span class="punctuation">,</span>
                       <span class="name">std</span><span class="operator">::</span><span class="name">pair</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="punctuation">,</span><span class="keyword type">int</span><span class="operator">&gt;</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">,</span><span class="name">N1</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">assert</span><span class="punctuation">(</span> <span class="name">y</span><span class="punctuation">.</span><span class="name">rank</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">2</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">y</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">N0</span> <span class="operator">-</span> <span class="literal number integer">2</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="name">y</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">N1</span> <span class="operator">-</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">y</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="operator">&amp;</span> <span class="name">x</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">1</span><span class="punctuation">)</span> <span class="punctuation">);</span>

<span class="comment single">// Using initializer_list of size 2 as an integral range
</span><span class="keyword">auto</span> <span class="name">z</span> <span class="operator">=</span> <span class="name">subarray</span><span class="punctuation">(</span> <span class="name">x</span> <span class="punctuation">,</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">N1</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">assert</span><span class="punctuation">(</span> <span class="name">z</span><span class="punctuation">.</span><span class="name">rank</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">1</span> <span class="punctuation">);</span>
<span class="name">assert</span><span class="punctuation">(</span> <span class="operator">&amp;</span> <span class="name">z</span><span class="punctuation">(</span><span class="literal number integer">0</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="operator">&amp;</span> <span class="name">x</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">1</span><span class="punctuation">)</span> <span class="punctuation">);</span>

<span class="comment single">// Conveniently extracting subarray for all of a extent
// without having to explicitly extract the dimensions.
</span><span class="keyword">auto</span> <span class="name">x</span> <span class="operator">=</span> <span class="name">subarray</span><span class="punctuation">(</span> <span class="name">x</span> <span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">all</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>
</pre>
<!--  -->
<p><tt class="docutils literal">subarray()</tt> returns an unspecified instantiation of <tt class="docutils literal">array_ref&lt;&gt;</tt>. There is
precedence in the standard for library functions with unspecified return types
(e.g. <tt class="docutils literal">bind()</tt>).</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">namespace</span> <span class="name">array_property</span> <span class="punctuation">{</span>

<span class="keyword">struct</span> <span class="name">all_type</span> <span class="punctuation">{};</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>

<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 multiline">/*unspecified array_ref&lt;&gt;*/</span>
<span class="name">subarray</span><span class="punctuation">(</span> <span class="keyword">const</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="operator">&amp;</span> <span class="name">ar</span> <span class="punctuation">,</span>
          <span class="name">SliceSpecifiers</span> <span class="punctuation">...</span> <span class="name">specs</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">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 multiline">/*unspecified array_property::dimension&lt;&gt;*/</span>
<span class="name">subdimensions</span><span class="punctuation">(</span> <span class="keyword">const</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="operator">&amp;</span> <span class="name">ar</span> <span class="punctuation">,</span>
               <span class="name">SliceSpecifiers</span> <span class="punctuation">...</span> <span class="name">specs</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">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">StrideSpecifiers</span> <span class="operator">&gt;</span>
<span class="comment multiline">/*unspecified array_ref&lt;&gt;*/</span>
<span class="name">stridearray</span><span class="punctuation">(</span> <span class="keyword">const</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="operator">&amp;</span> <span class="name">ar</span> <span class="punctuation">,</span>
             <span class="name">StrideSpecifiers</span> <span class="punctuation">...</span> <span class="name">specs</span><span class="punctuation">)</span> <span class="keyword">noexcept</span><span class="punctuation">;</span>

<span class="punctuation">}}</span>
</pre>
<!--  -->
<p><strong>template&lt; typename T , typename ... Properties , typename ... SliceSpecifiers &gt;</strong></p>
<p><strong>/*unspecified array_ref&lt;&gt;*/</strong></p>
<p><strong>subarray( const array_ref&lt; T, Properties ... &gt; &amp; ar , SliceSpecifiers ... specs) noexcept</strong></p>
<blockquote>
<p>Requires: <tt class="docutils literal"><span class="pre">sizeof...(Properties)</span> == <span class="pre">sizeof...(SliceSpecifiers)</span></tt></p>
<p>Requires: Each SliceSpecifier parameter must either be an integral type T, a
pair&lt;T, T&gt;, a tuple&lt;T, T&gt;, an initializer_list&lt;T&gt; with a size of 2, or an
array&lt;T, 2&gt;.</p>
<p>Requires: A SliceSpecifier parameter for dimension <tt class="docutils literal">i</tt> which expresses
a fixed index indices must be within the range <tt class="docutils literal">[ 0 , ar.extent(i) )</tt>.</p>
<p>Requires: A SliceSpecifier parameter for dimension <tt class="docutils literal">i</tt> which expresses
an interval of indices must be a subset of the range <tt class="docutils literal">[ 0 , ar.extent(i) )</tt>.</p>
<p>Returns: An array_ref&lt;&gt; referring to the same memory extent as the array_ref&lt;&gt;
<tt class="docutils literal">ar</tt>, with dimensions and layout specified by the SlicerSpecifier
parameters.</p>
<p>Remarks: For each SliceSpecifier parameter which is an integer value, the
produced array_ref&lt;&gt; will omit the corresponding dimension. E.g. the produced
array_ref&lt;&gt;'s rank will be is one less than the rank of <tt class="docutils literal">ar</tt>.</p>
</blockquote>
<pre class="code c++ literal-block">
<span class="name">assert</span><span class="punctuation">(</span><span class="name">subarray</span><span class="punctuation">(</span><span class="name">ar</span><span class="punctuation">,</span> <span class="name">x</span><span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">all</span><span class="punctuation">)(</span><span class="name">y</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="name">ar</span><span class="punctuation">(</span><span class="name">x</span><span class="punctuation">,</span> <span class="name">y</span><span class="punctuation">));</span>
<span class="name">assert</span><span class="punctuation">(</span><span class="name">subarray</span><span class="punctuation">(</span><span class="name">ar</span><span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">all</span><span class="punctuation">,</span> <span class="name">y</span><span class="punctuation">)(</span><span class="name">x</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="name">ar</span><span class="punctuation">(</span><span class="name">x</span><span class="punctuation">,</span> <span class="name">y</span><span class="punctuation">));</span>

<span class="name">assert</span><span class="punctuation">(</span><span class="name">subarray</span><span class="punctuation">(</span><span class="name">ar</span><span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">all</span><span class="punctuation">,</span> <span class="name">y</span><span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">all</span><span class="punctuation">)(</span><span class="name">x</span><span class="punctuation">,</span> <span class="name">z</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="name">ar</span><span class="punctuation">(</span><span class="name">x</span><span class="punctuation">,</span> <span class="name">y</span><span class="punctuation">,</span> <span class="name">z</span><span class="punctuation">));</span>
</pre>
<!--  -->
<blockquote>
Remarks: For each SliceSpecifier parameter which expresses an interval of
indices <tt class="docutils literal">[ a , b )</tt>, the produced array_ref&lt;&gt; will have extent
<tt class="docutils literal">[ 0 , b - a )</tt> in the corresponding dimension.</blockquote>
<pre class="code c++ literal-block">
<span class="comment single">// Ok
</span><span class="name">assert</span><span class="punctuation">(</span><span class="name">subarray</span><span class="punctuation">(</span><span class="name">ar</span><span class="punctuation">,</span> <span class="punctuation">{</span><span class="literal number integer">10</span><span class="punctuation">,</span> <span class="literal number integer">20</span><span class="punctuation">})(</span><span class="literal number integer">0</span><span class="punctuation">)</span>  <span class="operator">==</span> <span class="name">ar</span><span class="punctuation">(</span><span class="literal number integer">10</span><span class="punctuation">));</span>
<span class="name">assert</span><span class="punctuation">(</span><span class="name">subarray</span><span class="punctuation">(</span><span class="name">ar</span><span class="punctuation">,</span> <span class="punctuation">{</span><span class="literal number integer">10</span><span class="punctuation">,</span> <span class="literal number integer">20</span><span class="punctuation">})(</span><span class="literal number integer">10</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="name">ar</span><span class="punctuation">(</span><span class="literal number integer">20</span><span class="punctuation">));</span>

<span class="comment single">// Undefined behavior: subarray is out of bounds.
</span><span class="name">assert</span><span class="punctuation">(</span><span class="name">subarray</span><span class="punctuation">(</span><span class="name">ar</span><span class="punctuation">,</span> <span class="punctuation">{</span><span class="literal number integer">10</span><span class="punctuation">,</span> <span class="literal number integer">20</span><span class="punctuation">})(</span><span class="literal number integer">20</span><span class="punctuation">)</span> <span class="operator">==</span> <span class="name">ar</span><span class="punctuation">(</span><span class="literal number integer">20</span><span class="punctuation">));</span>
</pre>
<!--  -->
<p><strong>template&lt; typename T , typename ... Properties , typename ... SliceSpecifiers &gt;</strong></p>
<p><strong>/*unspecified array_property::dimension&lt;&gt;*/</strong></p>
<p><strong>subdimensions( const array_ref&lt; T, Properties ... &gt; &amp; ar , SliceSpecifiers ... specs) noexcept</strong></p>
<blockquote>
Returns: An array_property::dimension&lt;&gt; object referring to the dimensions
of the array_ref&lt;&gt; that would be constructed by calling subarray() on <tt class="docutils literal">ar</tt>
with SliceSpecifiers <tt class="docutils literal">specs</tt>.</blockquote>
<p><strong>template&lt; typename T , typename ... Properties , typename ... StrideSpecifiers &gt;</strong></p>
<p><strong>/*unspecified array_ref&lt;&gt;*/</strong></p>
<p><strong>stridearray( const array_ref&lt; T , Properties ... &gt; &amp; ar , StrideSpecifiers ... specs ) noexcept</strong></p>
<blockquote>
<p>Requires: <tt class="docutils literal"><span class="pre">sizeof...(Properties)</span> == <span class="pre">sizeof...(StrideSpecifiers)</span></tt></p>
<p>Requires: <tt class="docutils literal"><span class="pre">conjunction&lt;is_integral&lt;StrideSpecifiers&gt;::type...&gt;::value</span></tt></p>
<p>Requires: A StrideSpecifier parameter for dimension <tt class="docutils literal">i</tt> must be within
the range <tt class="docutils literal">[ 1 , ar.extent(i) )</tt>.</p>
<p>Returns: An array_ref&lt;&gt; referring to the same memory extent as the array_ref&lt;&gt;
<tt class="docutils literal">ar</tt> with the same rank as <tt class="docutils literal">ar</tt>, and dimensions and layout specified by
the StrideSpecifier parameters.</p>
<p>Remarks: The stride of the produced array_ref&lt;&gt; for a given dimension will be
the corresponding StrideSpecifier parameter.</p>
</blockquote>
</div>
<div class="section" id="limited-iterator-interface">
<h1>14&nbsp;&nbsp;&nbsp;Limited Iterator Interface</h1>
<p>A <strong>array_ref</strong> may have a non-isomorphic mapping between its
multi-index space (domain) and span of member memory (range).
For example, a subarray or dimension padded array will be
non-isomorphic.
An iterator for the members of a non-isomorphic array_ref must be
non-trivial in order to skip over non-member spans of memory.
Thus a general iterator implementation would necessarily
be non-trivial both in state and algorithm.
As such we provide a very limited iterator interface
conforming to <strong>24.6.5 range access</strong> for a rank-one array with
isomorphic layout (<em>e.g.</em>, default, <strong>layout_left</strong>, <strong>layout_right</strong>) and no
incompatible access intent properties
(<em>e.g.</em>, the <strong>reference</strong> type is truly a reference and not a proxy).
For example, a simple <strong>array_ref&lt;T[]&gt;</strong> will have <strong>begin</strong> and <strong>end</strong> overloads.</p>
<pre class="code c++ literal-block">
<span class="keyword">namespace</span> <span class="name">std</span> <span class="punctuation">{</span>

<span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">class</span> <span class="name class">T</span> <span class="punctuation">,</span> <span class="keyword">class</span> <span class="error">...</span><span class="name class">P</span> <span class="operator">&gt;</span>
<span class="comment single">// Enabled if rank one and isomorphic layout and no incompatible access
// intent properties.
</span><span class="keyword">typename</span> <span class="name">std</span><span class="operator">::</span><span class="name">enable_if</span><span class="operator">&lt;</span> <span class="comment multiline">/*unspecified*/</span>
                       <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span><span class="name">P</span><span class="punctuation">...</span><span class="operator">&gt;::</span><span class="name">pointer</span> <span class="operator">&gt;::</span><span class="name">type</span>
<span class="name">begin</span><span class="punctuation">(</span> <span class="keyword">const</span> <span class="name">std</span><span class="operator">::</span><span class="name">experimental</span><span class="operator">::</span><span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span><span class="name">P</span><span class="punctuation">...</span><span class="operator">&gt;</span> <span class="operator">&amp;</span> <span class="name">v</span> <span class="punctuation">)</span>
<span class="punctuation">{</span> <span class="keyword">return</span> <span class="name">v</span><span class="punctuation">.</span><span class="name">data</span><span class="punctuation">();</span> <span class="punctuation">}</span>

<span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">class</span> <span class="name class">T</span> <span class="punctuation">,</span> <span class="keyword">class</span> <span class="error">...</span><span class="name class">P</span> <span class="operator">&gt;</span>
<span class="comment single">// Enabled if rank one and isomorphic layout and no incompatible access
// intent properties.
</span><span class="keyword">typename</span> <span class="name">std</span><span class="operator">::</span><span class="name">enable_if</span><span class="operator">&lt;</span> <span class="comment multiline">/*unspecified*/</span>
                      <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span><span class="name">P</span><span class="punctuation">...</span><span class="operator">&gt;::</span><span class="name">pointer</span> <span class="operator">&gt;::</span><span class="name">type</span>
<span class="name">end</span><span class="punctuation">(</span> <span class="keyword">const</span> <span class="name">std</span><span class="operator">::</span><span class="name">experimental</span><span class="operator">::</span><span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span><span class="name">P</span><span class="punctuation">...</span><span class="operator">&gt;</span> <span class="operator">&amp;</span> <span class="name">v</span> <span class="punctuation">)</span>
<span class="punctuation">{</span> <span class="keyword">return</span> <span class="name">v</span><span class="punctuation">.</span><span class="name">data</span><span class="punctuation">()</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">.</span><span class="name">size</span><span class="punctuation">();</span> <span class="punctuation">}</span>

<span class="punctuation">}</span>
</pre>
<!--  -->
<p>Note that in the more general case of an isomorphic array_ref
of any rank a pointer (iterator) range for array_ref member data can be queried.</p>
<pre class="code c++ literal-block">
<span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">T</span> <span class="punctuation">,</span> <span class="keyword">class</span> <span class="error">... </span><span class="name class">P</span> <span class="operator">&gt;</span>
<span class="keyword type">void</span> <span class="name">foo</span><span class="punctuation">(</span> <span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span><span class="name">P</span><span class="punctuation">...</span><span class="operator">&gt;</span> <span class="name">a</span> <span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="keyword">if</span> <span class="punctuation">(</span> <span class="name">std</span><span class="operator">::</span><span class="name">is_reference</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span><span class="name">P</span><span class="punctuation">...</span><span class="operator">&gt;::</span><span class="name">reference</span> <span class="operator">&gt;::</span><span class="name">value</span>
       <span class="operator">&amp;&amp;</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">size</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">span</span><span class="punctuation">()</span> <span class="punctuation">)</span>
  <span class="punctuation">{</span>
    <span class="comment single">// Iteration via pointer type is valid and performant
</span>    <span class="keyword">typename</span> <span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span><span class="name">P</span><span class="punctuation">...</span><span class="operator">&gt;::</span><span class="name">pointer</span>
      <span class="name">begin</span> <span class="operator">=</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">data</span><span class="punctuation">()</span> <span class="punctuation">,</span>
      <span class="name">end</span>   <span class="operator">=</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">data</span><span class="punctuation">()</span> <span class="operator">+</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">span</span><span class="punctuation">()</span> <span class="punctuation">;</span>
  <span class="punctuation">}</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
</div>
<div class="section" id="example-usage-in-an-8th-order-finite-difference-stencil">
<h1>15&nbsp;&nbsp;&nbsp;Example Usage in an 8th Order Finite Difference Stencil</h1>
<p>The subarray interface provides a powerful mechanism for accessing
3-dimensional data in numerical kernels in a fashion which utilizes performant
memory access patterns and is amenable to compiler-assisted vectorization.</p>
<p>The following code is an example of a typical finite difference stencil which
might be used in a computational fluid dynamics application. This code utilizes
operator splitting to avoid vector register pressure and moves through memory
in unit stride to facilitate optimal memory access patterns. With the addition
of compiler alignment hints (as well as padding and aligned allocations to make
those assumptions true) and compiler directives or attributes to indicate that
the input pointers do not alias each other, this code would vectorize well on a
traditional x86 platform.</p>
<pre class="code c++ literal-block">
<span class="keyword type">void</span> <span class="name function">eighth_order_stencil</span><span class="punctuation">(</span>
  <span class="keyword">const</span> <span class="keyword type">double</span><span class="operator">*</span> <span class="name">V</span><span class="punctuation">,</span> <span class="keyword type">double</span><span class="operator">*</span> <span class="name">U</span><span class="punctuation">,</span>
  <span class="keyword type">ptrdiff_t</span> <span class="name">dx</span><span class="punctuation">,</span> <span class="keyword type">ptrdiff_t</span> <span class="name">dy</span><span class="punctuation">,</span> <span class="keyword type">ptrdiff_t</span> <span class="name">dz</span><span class="punctuation">,</span>
  <span class="name">array</span><span class="operator">&lt;</span><span class="keyword type">double</span><span class="punctuation">,</span> <span class="literal number integer">5</span><span class="operator">&gt;</span> <span class="name">c</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="comment single">// Iterate over interior points, skipping the 4 cell wide ghost
</span>  <span class="comment single">// zone region.
</span>  <span class="keyword">for</span> <span class="punctuation">(</span><span class="keyword type">int</span> <span class="name">iz</span> <span class="operator">=</span> <span class="literal number integer">4</span><span class="punctuation">;</span> <span class="name">iz</span> <span class="operator">&lt;</span> <span class="name">dz</span> <span class="operator">-</span> <span class="literal number integer">4</span><span class="punctuation">;</span> <span class="operator">++</span><span class="name">iz</span><span class="punctuation">)</span>
    <span class="keyword">for</span> <span class="punctuation">(</span><span class="keyword type">int</span> <span class="name">iy</span> <span class="operator">=</span> <span class="literal number integer">4</span><span class="punctuation">;</span> <span class="name">iy</span> <span class="operator">&lt;</span> <span class="name">dy</span> <span class="operator">-</span> <span class="literal number integer">4</span><span class="punctuation">;</span> <span class="operator">++</span><span class="name">iy</span><span class="punctuation">)</span> <span class="punctuation">{</span>
      <span class="comment single">// Pre-compute shared iy and iz indexing to ensure redundant
</span>      <span class="comment single">// calculations are avoided.
</span>      <span class="keyword type">double</span> <span class="keyword">const</span><span class="operator">*</span> <span class="name">v</span> <span class="operator">=</span> <span class="operator">&amp;</span><span class="name">V</span><span class="punctuation">[</span><span class="name">iy</span><span class="operator">*</span><span class="name">dx</span> <span class="operator">+</span> <span class="name">iz</span><span class="operator">*</span><span class="name">dx</span><span class="operator">*</span><span class="name">dy</span><span class="punctuation">];</span>
      <span class="keyword type">double</span><span class="operator">*</span>       <span class="name">u</span> <span class="operator">=</span> <span class="operator">&amp;</span><span class="name">U</span><span class="punctuation">[</span><span class="name">iy</span><span class="operator">*</span><span class="name">dx</span> <span class="operator">+</span> <span class="name">iz</span><span class="operator">*</span><span class="name">dx</span><span class="operator">*</span><span class="name">dy</span><span class="punctuation">];</span>

      <span class="comment single">// X-direction (unit stride) split.
</span>      <span class="keyword">for</span> <span class="punctuation">(</span><span class="keyword type">int</span> <span class="name">ix</span> <span class="operator">=</span> <span class="literal number integer">4</span><span class="punctuation">;</span> <span class="name">ix</span> <span class="operator">&lt;</span> <span class="name">dx</span> <span class="operator">-</span> <span class="literal number integer">4</span><span class="punctuation">;</span> <span class="operator">++</span><span class="name">ix</span><span class="punctuation">)</span>
        <span class="name">u</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">]</span> <span class="operator">=</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">0</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">]</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">1</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">2</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">2</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">2</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">3</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">4</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">4</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">4</span><span class="punctuation">]);</span>

      <span class="comment single">// Y-direction (dx stride) split.
</span>      <span class="keyword">for</span> <span class="punctuation">(</span><span class="keyword type">int</span> <span class="name">ix</span> <span class="operator">=</span> <span class="literal number integer">4</span><span class="punctuation">;</span> <span class="name">ix</span> <span class="operator">&lt;</span> <span class="name">dx</span> <span class="operator">-</span> <span class="literal number integer">4</span><span class="punctuation">;</span> <span class="operator">++</span><span class="name">ix</span><span class="punctuation">)</span>
        <span class="name">u</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">]</span> <span class="operator">+=</span> <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="name">dx</span><span class="punctuation">]</span>   <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="name">dx</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">2</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">2</span><span class="operator">*</span><span class="name">dx</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">2</span><span class="operator">*</span><span class="name">dx</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">3</span><span class="operator">*</span><span class="name">dx</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">3</span><span class="operator">*</span><span class="name">dx</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">4</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">4</span><span class="operator">*</span><span class="name">dx</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">4</span><span class="operator">*</span><span class="name">dx</span><span class="punctuation">]);</span>

      <span class="comment single">// Z-direction (dx*dy stride) split.
</span>      <span class="keyword">for</span> <span class="punctuation">(</span><span class="keyword type">int</span> <span class="name">ix</span> <span class="operator">=</span> <span class="literal number integer">4</span><span class="punctuation">;</span> <span class="name">ix</span> <span class="operator">&lt;</span> <span class="name">dx</span> <span class="operator">-</span> <span class="literal number integer">4</span><span class="punctuation">;</span> <span class="operator">++</span><span class="name">ix</span><span class="punctuation">)</span>
        <span class="name">u</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">]</span> <span class="operator">+=</span> <span class="name">c1</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="name">dx</span><span class="operator">*</span><span class="name">dy</span><span class="punctuation">]</span>   <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="name">dx</span><span class="operator">*</span><span class="name">dy</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c2</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">2</span><span class="operator">*</span><span class="name">dx</span><span class="operator">*</span><span class="name">dy</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">2</span><span class="operator">*</span><span class="name">dx</span><span class="operator">*</span><span class="name">dy</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c3</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">3</span><span class="operator">*</span><span class="name">dx</span><span class="operator">*</span><span class="name">dy</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">3</span><span class="operator">*</span><span class="name">dx</span><span class="operator">*</span><span class="name">dy</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c4</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">4</span><span class="operator">*</span><span class="name">dx</span><span class="operator">*</span><span class="name">dy</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">4</span><span class="operator">*</span><span class="name">dx</span><span class="operator">*</span><span class="name">dy</span><span class="punctuation">]);</span>
    <span class="punctuation">}</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
<p>The corresponding code can be rewritten using array_ref&lt;&gt; and the associated
subarray() interfaces.</p>
<pre class="code c++ literal-block">
<span class="keyword type">void</span> <span class="name function">eighth_order_stencil</span><span class="punctuation">(</span>
  <span class="name">array_ref</span><span class="operator">&lt;</span><span class="keyword">const</span> <span class="keyword type">double</span><span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</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="operator">&gt;</span><span class="punctuation">,</span> <span class="comment multiline">/*...*/</span><span class="operator">&gt;</span> <span class="name">V</span><span class="punctuation">,</span>
  <span class="name">array_ref</span><span class="operator">&lt;</span><span class="keyword type">double</span><span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</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="comment multiline">/*...*/</span><span class="operator">&gt;</span> <span class="name">U</span><span class="punctuation">,</span>
  <span class="name">array</span><span class="operator">&lt;</span><span class="keyword type">double</span><span class="punctuation">,</span> <span class="literal number integer">5</span><span class="operator">&gt;</span> <span class="name">c</span><span class="punctuation">)</span>
<span class="punctuation">{</span>
  <span class="comment single">// Compute the dimensions of the interior region.
</span>  <span class="keyword">auto</span> <span class="name">interior</span> <span class="operator">=</span> <span class="name">subdimensions</span><span class="punctuation">(</span><span class="name">V</span><span class="punctuation">,</span> <span class="punctuation">{</span><span class="literal number integer">4</span><span class="punctuation">,</span> <span class="name">V</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">4</span><span class="punctuation">},</span>
                                   <span class="punctuation">{</span><span class="literal number integer">4</span><span class="punctuation">,</span> <span class="name">V</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">4</span><span class="punctuation">},</span>
                                   <span class="punctuation">{</span><span class="literal number integer">4</span><span class="punctuation">,</span> <span class="name">V</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">4</span><span class="punctuation">});</span>

  <span class="keyword">for</span> <span class="punctuation">(</span><span class="keyword type">int</span> <span class="name">iz</span> <span class="operator">=</span> <span class="literal number integer">0</span><span class="punctuation">;</span> <span class="name">iz</span> <span class="operator">&lt;</span> <span class="name">interior</span><span class="punctuation">[</span><span class="literal number integer">2</span><span class="punctuation">];</span> <span class="operator">++</span><span class="name">iz</span><span class="punctuation">)</span>
    <span class="keyword">for</span> <span class="punctuation">(</span><span class="keyword type">int</span> <span class="name">iy</span> <span class="operator">=</span> <span class="literal number integer">0</span><span class="punctuation">;</span> <span class="name">iy</span> <span class="operator">&lt;</span> <span class="name">interior</span><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">];</span> <span class="operator">++</span><span class="name">iy</span><span class="punctuation">)</span> <span class="punctuation">{</span>
      <span class="comment single">// Pre-compute shared iy and iz indexing to ensure redundant
</span>      <span class="comment single">// calculations are avoided.
</span>      <span class="keyword">auto</span> <span class="name">v</span> <span class="operator">=</span> <span class="name">subarray</span><span class="punctuation">(</span><span class="name">V</span><span class="punctuation">,</span> <span class="punctuation">{</span><span class="literal number integer">4</span><span class="punctuation">,</span> <span class="name">V</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">4</span><span class="punctuation">},</span> <span class="name">iy</span><span class="punctuation">,</span> <span class="name">iz</span><span class="punctuation">);</span>
      <span class="keyword">auto</span> <span class="name">u</span> <span class="operator">=</span> <span class="name">subarray</span><span class="punctuation">(</span><span class="name">U</span><span class="punctuation">,</span> <span class="punctuation">{</span><span class="literal number integer">4</span><span class="punctuation">,</span> <span class="name">V</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">4</span><span class="punctuation">},</span> <span class="name">iy</span><span class="punctuation">,</span> <span class="name">iz</span><span class="punctuation">);</span>

      <span class="comment single">// X-direction (unit stride) split.
</span>      <span class="keyword">for</span> <span class="punctuation">(</span><span class="keyword type">int</span> <span class="name">ix</span> <span class="operator">=</span> <span class="literal number integer">0</span><span class="punctuation">;</span> <span class="name">ix</span> <span class="operator">&lt;</span> <span class="name">interior</span><span class="punctuation">[</span><span class="literal number integer">0</span><span class="punctuation">];</span> <span class="operator">++</span><span class="name">ix</span><span class="punctuation">)</span>
        <span class="name">u</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">]</span> <span class="operator">=</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">0</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">]</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">1</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">2</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">2</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">2</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">3</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">4</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">4</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">4</span><span class="punctuation">]);</span>

      <span class="comment single">// Y-direction (dx stride) split.
</span>      <span class="name">v</span> <span class="operator">=</span> <span class="name">stridearray</span><span class="punctuation">(</span><span class="name">v</span><span class="punctuation">,</span> <span class="name">V</span><span class="punctuation">.</span><span class="name">stride</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">));</span>
      <span class="name">u</span> <span class="operator">=</span> <span class="name">stridearray</span><span class="punctuation">(</span><span class="name">u</span><span class="punctuation">,</span> <span class="name">U</span><span class="punctuation">.</span><span class="name">stride</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">));</span>
      <span class="keyword">for</span> <span class="punctuation">(</span><span class="keyword type">int</span> <span class="name">ix</span> <span class="operator">=</span> <span class="literal number integer">0</span><span class="punctuation">;</span> <span class="name">ix</span> <span class="operator">&lt;</span> <span class="name">interior</span><span class="punctuation">[</span><span class="literal number integer">0</span><span class="punctuation">];</span> <span class="operator">++</span><span class="name">ix</span><span class="punctuation">)</span>
        <span class="name">u</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">]</span> <span class="operator">+=</span> <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">]</span>   <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">2</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">2</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">2</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">3</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">4</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">4</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">4</span><span class="punctuation">]);</span>

      <span class="comment single">// Z-direction (dx*dy stride) split.
</span>      <span class="name">v</span> <span class="operator">=</span> <span class="name">stridearray</span><span class="punctuation">(</span><span class="name">v</span><span class="punctuation">,</span> <span class="name">V</span><span class="punctuation">.</span><span class="name">stride</span><span class="punctuation">(</span><span class="literal number integer">2</span><span class="punctuation">));</span>
      <span class="name">u</span> <span class="operator">=</span> <span class="name">stridearray</span><span class="punctuation">(</span><span class="name">u</span><span class="punctuation">,</span> <span class="name">U</span><span class="punctuation">.</span><span class="name">stride</span><span class="punctuation">(</span><span class="literal number integer">2</span><span class="punctuation">));</span>
      <span class="keyword">for</span> <span class="punctuation">(</span><span class="keyword type">int</span> <span class="name">ix</span> <span class="operator">=</span> <span class="literal number integer">0</span><span class="punctuation">;</span> <span class="name">ix</span> <span class="operator">&lt;</span> <span class="name">interior</span><span class="punctuation">[</span><span class="literal number integer">0</span><span class="punctuation">];</span> <span class="operator">++</span><span class="name">ix</span><span class="punctuation">)</span>
        <span class="name">u</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">]</span> <span class="operator">+=</span> <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">1</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">]</span>   <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">2</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">2</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">2</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">3</span><span class="punctuation">])</span>
              <span class="operator">+</span>  <span class="name">c</span><span class="punctuation">[</span><span class="literal number integer">4</span><span class="punctuation">]</span> <span class="operator">*</span> <span class="punctuation">(</span><span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">+</span><span class="literal number integer">4</span><span class="punctuation">]</span> <span class="operator">+</span> <span class="name">v</span><span class="punctuation">[</span><span class="name">ix</span><span class="operator">-</span><span class="literal number integer">4</span><span class="punctuation">]);</span>
    <span class="punctuation">}</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
<p>Slicing down to a 1-dimensional array_ref&lt;&gt; in the inner-most unit-stride loops
also facilitates the use of the 1-dimensional iterator interface, enabling
interoperability with iterator-based algorithms.</p>
</div>
<div class="section" id="array-reference-property-member-access-array-bounds-checking">
<h1>16&nbsp;&nbsp;&nbsp;Array Reference Property : Member Access Array Bounds Checking</h1>
<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">namespace</span> <span class="name">array_property</span> <span class="punctuation">{</span>

<span class="keyword">struct</span> <span class="name">bounds_checking</span> <span class="punctuation">;</span>

<span class="punctuation">}}}</span>
</pre>
<!--  -->
<p>Array bounds checking is an invaluable tool for debugging user code.
This functionality traditionally requires global injection through
special compiler support.
In large, long running code global array bounds checking introduces
a significant overhead that impedes the debugging process.
A member access array bounds checking array property allows
the selective injection of array bounds checking and removes
the need for special compiler support.</p>
<pre class="code c++ literal-block">
<span class="comment single">// User enables array bounds checking for selected array_ref.
</span>
<span class="keyword">using</span> <span class="name">x_property</span> <span class="operator">=</span> <span class="keyword">typename</span> <span class="name">std</span><span class="operator">::</span><span class="name">conditional</span><span class="operator">&lt;</span>
    <span class="name">ENABLE_ARRAY_BOUNDS_CHECKING</span> <span class="punctuation">,</span> <span class="name">array_property</span><span class="operator">::</span><span class="name">bounds_checking</span> <span class="punctuation">,</span> <span class="keyword type">void</span>
<span class="operator">&gt;::</span><span class="name">type</span> <span class="punctuation">;</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">array_property</span><span class="operator">::</span><span class="name">dimension</span><span class="operator">&lt;</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">3</span><span class="operator">&gt;</span> <span class="punctuation">,</span> <span class="name">x_property</span> <span class="operator">&gt;</span>
    <span class="name">x</span><span class="punctuation">(</span><span class="name">ptr</span><span class="punctuation">,</span><span class="name">N0</span><span class="punctuation">,</span><span class="name">N1</span><span class="punctuation">);</span>
</pre>
<!--  -->
<p>Adding <strong>bounds_checking</strong> to the properties of an array has the
effect of introducing an array bounds check to each member access operation.
If the requirement <tt class="docutils literal">0 &lt;= i# &lt; <span class="pre">extent_#()</span></tt> fails an error message is generated
and the member access operator aborts as it is <strong>noexcept</strong>.</p>
</div>
<div class="section" id="preferred-syntax-for-multidimensional-array-with-multiple-implicit-dimensions">
<h1>17&nbsp;&nbsp;&nbsp;Preferred Syntax for Multidimensional Array with Multiple Implicit Dimensions</h1>
<p id="relaxation-of-the-current-multidimensional-array-type-declaration">One goal of the array_ref interface is to preserve syntax
between array_ref and arrays with explicit and implicitly declared dimensions.
In the following example foo1 and foo2 accept rank 3 arrays of integers
with prescribed explicit / implicit dimensions and fooT accepts a rank 3
array of integers with unprescribed dimensions.</p>
<pre class="code c++ literal-block">
<span class="keyword type">void</span> <span class="name function">foo1</span><span class="punctuation">(</span> <span class="name">array_ref</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[</span> <span class="punctuation">][</span><span class="literal number integer">3</span><span class="punctuation">][</span><span class="literal number integer">3</span><span class="punctuation">]</span> <span class="operator">&gt;</span> <span class="name">a</span> <span class="punctuation">);</span> <span class="comment single">// Two explicit dimensions
</span><span class="keyword type">void</span> <span class="name function">foo2</span><span class="punctuation">(</span> <span class="name">array_ref</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[</span> <span class="punctuation">][</span> <span class="punctuation">][</span> <span class="punctuation">]</span> <span class="operator">&gt;</span> <span class="name">a</span> <span class="punctuation">);</span> <span class="comment single">// All implicit dimensions
</span>
<span class="comment single">// Accept a array_ref of a rank three array with value type int
// and dimensions are explicit or implicit.
</span><span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">class</span> <span class="name class">T</span> <span class="punctuation">,</span> <span class="keyword">class</span> <span class="error">... </span><span class="name class">P</span> <span class="operator">&gt;</span>
<span class="keyword">typename</span> <span class="name">std</span><span class="operator">::</span><span class="name">enable_if</span><span class="operator">&lt;</span> <span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span><span class="name">P</span><span class="punctuation">...</span><span class="operator">&gt;::</span><span class="name">rank</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">3</span> <span class="operator">&gt;::</span><span class="name">type</span>
<span class="name">foo</span><span class="punctuation">(</span> <span class="name">array_ref</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span><span class="name">P</span><span class="punctuation">...</span><span class="operator">&gt;</span> <span class="name">a</span> <span class="punctuation">)</span> <span class="punctuation">{</span> <span class="punctuation">...</span> <span class="punctuation">}</span>

<span class="keyword type">void</span> <span class="name">bar</span><span class="punctuation">()</span>
<span class="punctuation">{</span>
  <span class="keyword">enum</span> <span class="punctuation">{</span> <span class="name">L</span> <span class="operator">=</span> <span class="punctuation">...</span> <span class="punctuation">};</span>
  <span class="keyword type">int</span> <span class="name">buffer</span><span class="punctuation">[</span> <span class="name">L</span> <span class="operator">*</span> <span class="literal number integer">3</span> <span class="operator">*</span> <span class="literal number integer">3</span> <span class="punctuation">];</span>
  <span class="name">array_ref</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][][]</span> <span class="operator">&gt;</span> <span class="name">a</span><span class="punctuation">(</span> <span class="name">buffer</span> <span class="punctuation">,</span> <span class="name">L</span> <span class="punctuation">,</span> <span class="literal number integer">3</span> <span class="punctuation">,</span> <span class="literal number integer">3</span> <span class="punctuation">);</span>

  <span class="name">assert</span><span class="punctuation">(</span> <span class="literal number integer">3</span> <span class="operator">==</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">rank</span><span class="punctuation">()</span> <span class="punctuation">);</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="name">L</span> <span class="operator">==</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="punctuation">);</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="literal number integer">3</span> <span class="operator">==</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="punctuation">);</span>
  <span class="name">assert</span><span class="punctuation">(</span> <span class="literal number integer">3</span> <span class="operator">==</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="name">assert</span><span class="punctuation">(</span> <span class="name">a</span><span class="punctuation">.</span><span class="name">size</span><span class="punctuation">()</span> <span class="operator">==</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">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="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="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>

  <span class="name">foo</span><span class="punctuation">(</span> <span class="name">array</span> <span class="punctuation">);</span>
<span class="punctuation">}</span>
</pre>
<!--  -->
<div class="section" id="a-relaxed-multidimensional-array-type-declaration">
<h2>17.1&nbsp;&nbsp;&nbsp;A relaxed multidimensional array type declaration</h2>
<p>The current array type declarator constraints are defined in in <strong>n4567 8.3.4.p3</strong> as follows.</p>
<blockquote>
<em>When several “array of” specifications are adjacent,
a multidimensional array type is created;
only the first of the constant expressions that
specify the bounds of the arrays may be omitted.
In addition to declarations in which an incomplete
object type is allowed, an array bound may be omitted
in some cases in the declaration of a function parameter (8.3.5).
An array bound may also be omitted when the declarator is
followed by an initializer (8.5).
In this case the bound is calculated from the
number of initial elements (say, N) supplied (8.5.1),
and the type of the identifier of D is “array of N T”.
Furthermore, if there is a preceding declaration
of the entity in the same scope in which the bound was specified,
an omitted array bound is taken to be the same as in that
earlier declaration, and similarly for the definition
of a static data member of a class.</em></blockquote>
<p>The preferred syntax requires a relaxation of
array type declarator constraints defined in <strong>n4567 8.3.4.p3</strong>
exclusively for an incomplete object type.
The following wording change is recommended.</p>
<blockquote>
<em>When several “array of” specifications are adjacent,
a multidimensional array type is created.
In declarations in which an incomplete object type is allowed
any of the constant expressions that specify bounds
of the arrays may be omitted.
In some cases in the declaration of a function parameter (8.3.5)
the first array bound constant expression may be omitted.
The first array bound constant expression
may also be omitted when the declarator is
followed by an initializer (8.5).
In this case the bound is calculated from the
number of initial elements (say, N) supplied (8.5.1),
and the type of the identifier of D is “array of N T”.
Furthermore, if there is a preceding declaration
of the entity in the same scope in which the bound was specified,
the omitted first array bound constant expression is
taken to be the same as in that
earlier declaration, and similarly for the definition
of a static data member of a class.</em></blockquote>
<p><strong>This minor language specification change has been implemented with
a trivial (one line) patch to Clang and was permissible in gcc prior to
version 5.</strong></p>
</div>
</div>
</div>
</body>
</html>
