<?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>P0009r00 : Polymorphic Multidimensional Array View</title>
<meta name="author" content="H. Carter Edwards" />
<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" />
<meta name="author" content="Bryce Lelbach" />
<meta name="date" content="2015-09-23" />
<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="p0009r00-polymorphic-multidimensional-array-view">
<h1 class="title">P0009r00 : Polymorphic Multidimensional Array View</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<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>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><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 class="field"><th class="docinfo-name">Number:</th><td class="field-body">P0009</td>
</tr>
<tr><th class="docinfo-name">Version:</th>
<td>00</td></tr>
<tr><th class="docinfo-name">Date:</th>
<td>2015-09-23</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>
<tr class="field"><th class="docinfo-name">WG21:</th><td class="field-body">Library Evolution Working Group (LEWG)</td>
</tr>
<tr class="field"><th class="docinfo-name">WG21:</th><td class="field-body">Evolution Working Group (EWG) for array declaration</td>
</tr>
</tbody>
</table>
<div class="section" id="rationale-for-polymorphic-multidimensional-array-view">
<h1>1&nbsp;&nbsp;&nbsp;Rationale for polymorphic multidimensional array view</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 multidimensional array is a <strong>view</strong> to a memory extent
through a <strong>layout</strong> mapping from a multi-index space (domain) to that extent (range).
A view's 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 view abstraction with polymorphic layout is required
to enable changing array layout 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 views 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.
As such deviations from the Kokkos interface that leverage C++2011
capabilities which are included in this proposed have been
successfully prototyped in a separate repository
(github.com/kokkos/PolyView).</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>view</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 viewed data resides and algorithmic access intent properties.
Examples of access intent properties include
(1)  <em>read-only random with locality</em> such that member queries are
performed through GPU texture cache hardware for GPU memory spaces,
(2) <em>atomic</em> such that member access operations are overloaded
via proxy objects to atomic operations (see P0019, Atomic View),
(3) <em>non-temporal</em> such that member access operations can be overloaded
with non-caching reads and writes, and
(4) <em>restrict</em> to guarantee non-aliasing of viewed data within the current context.</p>
</div>
<div class="section" id="compare-and-contrast-summary-re-previous-array-view-proposal">
<h1>3&nbsp;&nbsp;&nbsp;Compare and contrast summary re: previous <strong>array_view</strong> proposal</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>Furthemore, this proposal provides a path for seemless extensibility
for view properties beyond array dimensions and array layout.
Thus we choose the name <strong>view</strong> as opposed to <strong>array_view</strong>
in anticipation of this new fundamental mechanism for <em>viewing</em>
spans of memory with an easily extensible set of properties.</p>
</div>
<div class="section" id="the-view">
<h1>4&nbsp;&nbsp;&nbsp;The View</h1>
<p>The proposed <strong>view</strong> has template arguments for the data type of the array
and a parameter pack for polymorphic properties of the view.</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; class DataType , class ... Properties &gt;</div>
<div class="line">struct view ;</div>
</div>
<div class="line">}}</div>
</div>
</blockquote>
<p>The complete proposed specification for <strong>view</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 view properties are proposed.
These properties are defined by class and templated class types.
It is an open question as to whether these view properties
should resided in the same namespace as the <strong>view</strong>,
or in a designated namespace such as the <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 view_property {</div>
<div class="line-block">
<div class="line">// view property classes</div>
</div>
<div class="line">}}}</div>
</div>
</blockquote>
</div>
<div class="section" id="view-of-a-one-dimensional-array">
<h1>5&nbsp;&nbsp;&nbsp;View of a One-Dimensional Array</h1>
<p>A view of a one-dimension array is anticipated to subsume the functionality
of a pointer to 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">array</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">array</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">view</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[]</span> <span class="operator">&gt;</span> <span class="name">array</span> <span class="punctuation">);</span> <span class="comment single">// View API
</span><span class="keyword type">void</span> <span class="name function">foo</span><span class="punctuation">(</span> <span class="name">view</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">array</span> <span class="punctuation">);</span> <span class="comment single">// View 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">view</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="punctuation">[]</span><span class="operator">&gt;</span> <span class="name">array</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">array</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">array</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 a view is analogous to the <em>const-ness</em> of a pointer.
A const-view is similar to a const-pointer in that the view may not be
modifid but the viewed extent of memory may be modified.
A view-of-const is similar to a pointer-to-const in that the viewed
extent of memory may not be modified.</p>
</div>
<div class="section" id="view-of-traditional-multidimensional-array-with-explicit-dimensions">
<h1>6&nbsp;&nbsp;&nbsp;View of 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">array</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">view</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">array</span> <span class="punctuation">);</span> <span class="comment single">// View 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">view</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">array</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">array</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">array</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">array</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">array</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">array</span><span class="punctuation">.</span><span class="name">size</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="name">array</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">array</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">array</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">array</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>
<div class="section" id="view-of-multidimensional-array-with-multiple-implicit-dimensions-preferred">
<h1>7&nbsp;&nbsp;&nbsp;View of Multidimensional Array with Multiple Implicit Dimensions (Preferred)</h1>
<p><strong>Requires slight language specification change for correction and relaxation of array declaration.</strong></p>
<p>Multidimensional arrays are used with multiple implicit dimensions;
i.e., more dimensions than the leading dimension are declared at runtime.
Such arrays are implemented within applications and libraries with
numerous design idioms.</p>
<p>A minimalist design that preserves the appearance of conventional
multidimensional array syntax follows an <em>array of pointers to array of pointers to ...</em> idiom.
While dereferencing operations are syntactically compatible with
an array of explicitly declared dimensions this idiom provides
no locality guarantees for members of the array,
consumes significant memory for the arrays of pointers,
and is problematic when passing such arrays to functions.</p>
<pre class="code c++ literal-block">
<span class="keyword type">double</span> <span class="operator">***</span> <span class="name">x</span> <span class="punctuation">;</span>
<span class="name">x</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="keyword type">double</span> <span class="operator">**</span><span class="punctuation">[</span><span class="name">N0</span><span class="punctuation">];</span>
<span class="keyword">for</span> <span class="punctuation">(</span> <span class="keyword type">size_t</span> <span class="name">i0</span> <span class="operator">=</span> <span class="literal number integer">0</span> <span class="punctuation">;</span> <span class="name">i0</span> <span class="operator">&lt;</span> <span class="name">N0</span> <span class="punctuation">;</span> <span class="operator">++</span><span class="name">i0</span> <span class="punctuation">)</span> <span class="punctuation">{</span>
  <span class="name">x</span><span class="punctuation">[</span><span class="name">i0</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="keyword type">double</span> <span class="operator">*</span><span class="punctuation">[</span><span class="name">N1</span><span class="punctuation">];</span>
  <span class="keyword">for</span> <span class="punctuation">(</span> <span class="keyword type">size_t</span> <span class="name">i1</span> <span class="operator">=</span> <span class="literal number integer">0</span> <span class="punctuation">;</span> <span class="name">i1</span> <span class="operator">&lt;</span> <span class="name">N1</span> <span class="punctuation">;</span> <span class="operator">++</span><span class="name">i1</span> <span class="punctuation">)</span> <span class="punctuation">{</span>
    <span class="name">x</span><span class="punctuation">[</span><span class="name">i0</span><span class="punctuation">][</span><span class="name">i1</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="keyword type">double</span><span class="punctuation">[</span><span class="name">N2</span><span class="punctuation">]</span> <span class="punctuation">;</span>
  <span class="punctuation">}</span>
<span class="punctuation">}</span>

<span class="name">x</span><span class="punctuation">[</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="punctuation">]</span> <span class="comment single">// member access
</span>
<span class="name">foo</span><span class="punctuation">(</span> <span class="keyword type">double</span> <span class="operator">*</span><span class="keyword">const</span> <span class="operator">*</span><span class="keyword">const</span> <span class="operator">*</span> <span class="keyword">const</span> <span class="name">array</span> <span class="punctuation">,</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>
</pre>
<!--  -->
<p>A major goal of the <strong>view</strong> interface is to preserve compatibility
between views to 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">view</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">array</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">view</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">array</span> <span class="punctuation">);</span> <span class="comment single">// All implicit dimensions
</span>
<span class="comment single">// Accept a view 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">view</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">view</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">array</span> <span class="punctuation">);</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">view</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][][]</span> <span class="operator">&gt;</span> <span class="name">array</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">array</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">array</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">array</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">array</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">array</span><span class="punctuation">.</span><span class="name">size</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="name">array</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">array</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">array</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">array</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="relaxed-array-type-declarator">
<h2>7.1&nbsp;&nbsp;&nbsp;Relaxed array type declarator</h2>
<p>The current array type declarator constraints are defined in in <strong>8.3.4 Arrays paragraph 3</strong> as follows.</p>
<blockquote>
<em>When several “array of” specifications are adjacent,
a multidimensional array is created;
only the first of the constant expressions
that specify the bounds of the arrays may be omitted.</em></blockquote>
<p>Note that this existing specification is in error when
array syntax is used in a type definition -
a type definition does not create a multidimensional array.</p>
<pre class="code c++ literal-block">
<span class="keyword">typedef</span> <span class="keyword type">int</span> <span class="name">X</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="comment single">// does not create a multidimensional array
</span><span class="keyword">using</span> <span class="name">Y</span> <span class="operator">=</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">3</span><span class="punctuation">]</span> <span class="punctuation">;</span> <span class="comment single">// does not create a multidimensional array</span>
</pre>
<!--  -->
<p>This syntax requires a relaxation of array type declarator constraints defined in <strong>8.3.4 Arrays paragraph 3</strong>.</p>
<p>Relaxing the <strong>8.3.4.p3</strong> constraint as follows will</p>
<blockquote>
<ul class="simple">
<li>clarify the difference between array type and array object declarations,</li>
<li>preserve correctness for conventional array object declarations,</li>
<li>allow the proposed syntax for a view of an array with multiple implicit dimensions, and</li>
<li>have zero impact on a compiler's processing of executable statements.</li>
</ul>
<p><em>When several “array of” specifications are adjacent
to form a multidimensional array type specification
and that type is used in the explicit declaration of a
multidimensional array then only the first of the
sequence of array bound constant expressions may be omitted;
otherwise any or all of the array bound constant expressions may be omitted.</em></p>
</blockquote>
<p>There exists at least two precedents for types that can be defined but not used to declare objects:
(1) an array with an omitted leading bound and (2) <strong>void</strong>.</p>
<p>Relaxing this constraint is a simple one-line change in Clang that merely disables the error message and
allows omission of second and subsequent dimensions.</p>
<p>In gcc 4.7, 4.8, and 4.9 this relaxation was implicitly supported as
demonstrated by the following error-free and warning-free meta function.</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 type">unsigned</span> <span class="name">R</span> <span class="operator">&gt;</span>
<span class="keyword">struct</span> <span class="name">implicit_array_type</span> <span class="punctuation">{</span> <span class="keyword">using</span> <span class="name">type</span> <span class="operator">=</span> <span class="keyword">typename</span> <span class="name">implicit_array_type</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span><span class="name">R</span><span class="operator">-</span><span class="literal number integer">1</span><span class="operator">&gt;::</span><span class="name">type</span><span class="punctuation">[]</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">T</span> <span class="operator">&gt;</span>
<span class="keyword">struct</span> <span class="name">implicit_array_type</span><span class="operator">&lt;</span><span class="name">T</span><span class="punctuation">,</span><span class="literal number integer">0</span><span class="operator">&gt;</span> <span class="punctuation">{</span> <span class="keyword">using</span> <span class="name">type</span> <span class="operator">=</span> <span class="name">T</span> <span class="punctuation">;</span> <span class="punctuation">};</span>

<span class="keyword">using</span> <span class="name">array_rank_3</span> <span class="operator">=</span> <span class="keyword">typename</span> <span class="name">implicit_array_type</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="operator">&gt;::</span><span class="name">type</span> <span class="punctuation">;</span>
</pre>
<!--  -->
</div>
<div class="section" id="simplification-for-array-with-all-implicit-dimensions">
<h2>7.2&nbsp;&nbsp;&nbsp;Simplification for array with all implicit dimensions</h2>
<p>A <em>properties</em> mechanism is defined to simplify declaration
of a view to array of rank <strong>R</strong> with all-implicit dimensions.</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 type">unsigned</span> <span class="name">R</span> <span class="operator">&gt;</span>
<span class="keyword">using</span> <span class="name">array_view</span> <span class="operator">=</span> <span class="name">view</span><span class="operator">&lt;</span> <span class="name">T</span> <span class="punctuation">,</span> <span class="name">view_property</span><span class="operator">::</span><span class="name">implicit_dimensions</span><span class="operator">&lt;</span> <span class="name">R</span> <span class="operator">&gt;</span> <span class="operator">&gt;</span> <span class="punctuation">;</span>

<span class="comment single">// Equivalent types:
</span><span class="name">array_view</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="operator">&gt;</span>
<span class="name">view</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="punctuation">[][][]</span><span class="operator">&gt;</span>
</pre>
<!--  -->
</div>
</div>
<div class="section" id="view-of-multidimensional-array-with-multiple-implicit-dimensions-alternative">
<h1>8&nbsp;&nbsp;&nbsp;View of Multidimensional Array with Multiple Implicit Dimensions (alternative)</h1>
<p>If the array declaration constraint in <strong>8.3.4.p3</strong> is not relaxed then
an alternative mechanism will be required to define mixed explicit and implicit
dimensions through a view dimension property.
A dimension property is syntactically more verbose and requires 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">view</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="name">N1</span><span class="punctuation">);</span> <span class="comment single">// preferred concise syntax
</span><span class="name">view</span><span class="operator">&lt;</span> <span class="keyword type">int</span> <span class="punctuation">,</span> <span class="name">view_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">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="comment single">// verbose syntax
</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">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">2</span> <span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">==</span> <span class="literal number integer">3</span> <span class="punctuation">);</span>

<span class="name">assert</span><span class="punctuation">(</span> <span class="name">view_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="name">extent_0</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">view_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="name">extent_1</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">view_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="name">extent_2</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">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="name">N0</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="name">N1</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">2</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">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="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="name">N1</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>
</pre>
<!--  -->
<p>If this alternative <em>properties</em> mechanism is required then the
simple array declaration syntax is still available and will
be supported when only the leading dimension is implicit.</p>
<pre class="code c++ literal-block">
<span class="name">view</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[]</span> <span class="operator">&gt;</span> <span class="name">x</span> <span class="punctuation">;</span> <span class="comment single">// concise syntax
</span><span class="name">view</span><span class="operator">&lt;</span> <span class="keyword type">int</span> <span class="punctuation">,</span> <span class="name">view_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="operator">&gt;</span> <span class="operator">&gt;</span> <span class="name">y</span> <span class="punctuation">;</span> <span class="comment single">// property syntax</span>
</pre>
<!--  -->
<p>A concern with this alternative <em>properties</em> mechanism is that
if a zero value becomes accepted within dimension statements
then there is potential confusion between implicit dimensions
and explicit dimensions of zero.
For example, are the following declarations equivalent?</p>
<pre class="code c++ literal-block">
<span class="name">view</span><span class="operator">&lt;</span><span class="keyword type">int</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">&gt;</span> <span class="comment single">// If permitted
</span><span class="name">view</span><span class="operator">&lt;</span><span class="keyword type">int</span><span class="punctuation">,</span> <span class="name">view_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>
</pre>
<!--  -->
</div>
<div class="section" id="view-properties-layout-polymorphism">
<h1>9&nbsp;&nbsp;&nbsp;View Properties: Layout Polymorphism</h1>
<p>The <strong>view::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 viewed 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.
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 view property template parameter specifies a layout mapping.
If this property is omitted the layout mapping of the view
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>, 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 view_property {</div>
<div class="line-block">
<div class="line">struct layout_right ;</div>
<div class="line">struct layout_left ;</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">view</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][][]</span> <span class="operator">&gt;</span> <span class="name">view_native</span> <span class="punctuation">;</span>
<span class="keyword">typedef</span> <span class="name">view</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][][]</span> <span class="punctuation">,</span> <span class="name">view_property</span><span class="operator">::</span><span class="name">layout_right</span> <span class="operator">&gt;</span> <span class="name">view_right</span> <span class="punctuation">;</span>
<span class="keyword">typedef</span> <span class="name">view</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][][]</span> <span class="punctuation">,</span> <span class="name">view_property</span><span class="operator">::</span><span class="name">layout_left</span> <span class="operator">&gt;</span>  <span class="name">view_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">view_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">view_right</span> <span class="operator">::</span><span class="name">layout</span> <span class="punctuation">,</span> <span class="name">view_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">view_left</span>  <span class="operator">::</span><span class="name">layout</span> <span class="punctuation">,</span> <span class="name">view_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">view_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">view_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">view_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_stride</strong> mapping is regular; however, it may
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="view-properties-extensible-layout-polymorphism">
<h1>10&nbsp;&nbsp;&nbsp;View Properties: Extensible Layout Polymorphism</h1>
<p>The <strong>view</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.</p>
<p>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>subviews</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="view-properties-flexibility-and-extensibility">
<h1>11&nbsp;&nbsp;&nbsp;View Properties: Flexibility and Extensibility</h1>
<p>One or more view properties of <strong>void</strong> are acceptable and have no effect.
This allows user code to define a template argument list of potential
view properties and then enabling/disabling a particular property
by conditionally setting it to <strong>void</strong>.  For example:</p>
<pre class="code c++ literal-block">
<span class="keyword">typedef</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">AllowPadding</span> <span class="punctuation">,</span> <span class="name">view_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="name">layout</span> <span class="punctuation">;</span>

<span class="comment single">// If AllowPadding then use layout_right else use native layout
</span><span class="keyword">typedef</span> <span class="name">view</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][][]</span> <span class="punctuation">,</span> <span class="name">layout</span> <span class="operator">&gt;</span> <span class="name">MyViewType</span> <span class="punctuation">;</span>
</pre>
<!--  -->
</div>
<div class="section" id="specification-with-simple-view-properties">
<h1>12&nbsp;&nbsp;&nbsp;Specification with Simple View Properties</h1>
<p>Simple view properties include the array layout and if necessary
a <strong>view_property::dimension</strong> type for arrays with multiple implicit dimensions.
View properties are provided through a variadic template to
support extensibility of the view.
Possible additional properties include array bounds checking,
atomic access to members, memory space within a heterogeneous
memory architecture, and user access pattern hints.</p>
<blockquote>
<div class="line-block">
<div class="line">namespace std {</div>
<div class="line">namespace experimental {</div>
<div class="line"><br /></div>
<div class="line">template&lt; class DataType , class ... Properties &gt;</div>
<div class="line">struct view {</div>
<div class="line-block">
<div class="line">//--------------------</div>
<div class="line">// Types:</div>
<div class="line"><br /></div>
<div class="line">// Types are implementation and Properties dependent.</div>
<div class="line">// The following type implementation are normative</div>
<div class="line">// with respect to empty Properties.</div>
<div class="line"><br /></div>
<div class="line">using value_type = typename std::remove_all_extents&lt; DataType &gt;::type ;</div>
<div class="line">using reference  = value_type &amp; ; // Typical type, but implementation defined</div>
<div class="line">using pointer    = value_type * ; // Typical type, but implementation defined</div>
<div class="line"><br /></div>
<div class="line">//--------------------</div>
<div class="line">// Domain index space properties:</div>
<div class="line"><br /></div>
<div class="line">static constexpr unsigned rank() const ;</div>
<div class="line"><br /></div>
<div class="line">template&lt; typename IntegralType &gt;</div>
<div class="line">constexpr size_t extent( const IntegralType &amp; ) const ;</div>
<div class="line"><br /></div>
<div class="line">// Cardinality of index space; i.e., product of extents</div>
<div class="line">constexpr size_t  size() const ;</div>
<div class="line"><br /></div>
<div class="line">//--------------------</div>
<div class="line">// Layout mapping properties:</div>
<div class="line"><br /></div>
<div class="line">using layout     = <em>array layout type</em> ;</div>
<div class="line">using is_regular = std::integral_constant&lt;bool, <em>B</em> &gt; ;</div>
<div class="line"><br /></div>
<div class="line">// If the layout mapping is regular then return the</div>
<div class="line">// distance between members when index # is increased by one.</div>
<div class="line">template&lt; typename IntegralType &gt;</div>
<div class="line">constexpr size_t stride( const IntegralType &amp; ) const ;</div>
<div class="line"><br /></div>
<div class="line">// Span covering the members</div>
<div class="line">constexpr size_t span() const ;</div>
<div class="line"><br /></div>
<div class="line">// Span of an array with regular layout if it</div>
<div class="line">// is constructed with the given implicit dimensions.</div>
<div class="line">static constexpr</div>
<div class="line-block">
<div class="line">size_t span( size_t implicit_N0</div>
<div class="line-block">
<div class="line">, size_t implicit_N1 = 0</div>
<div class="line">, size_t implicit_N2 = 0</div>
<div class="line">, size_t implicit_N3 = 0</div>
<div class="line">, size_t implicit_N4 = 0</div>
<div class="line">, size_t implicit_N5 = 0</div>
<div class="line">, size_t implicit_N6 = 0</div>
<div class="line">, size_t implicit_N7 = 0</div>
<div class="line">, size_t implicit_N8 = 0</div>
<div class="line">, size_t implicit_N9 = 0</div>
<div class="line">);</div>
<div class="line"><br /></div>
</div>
</div>
<div class="line">// Pointer to member memory</div>
<div class="line">constexpr pointer data() const ;</div>
<div class="line"><br /></div>
<div class="line">//--------------------</div>
<div class="line">// Member access (proper):</div>
<div class="line"><br /></div>
<div class="line">// EnableIf rank == 0</div>
<div class="line">reference operator()() const ;</div>
<div class="line"><br /></div>
<div class="line">// EnableIf rank == 1 and std::is_integral&lt;t0&gt;::value</div>
<div class="line">template&lt; typename t0 &gt;</div>
<div class="line">reference operator[]( const t0 &amp; i0 ) const ;</div>
<div class="line"><br /></div>
<div class="line">// EnableIf rank == 1 and std::is_integral&lt;t0&gt;::value</div>
<div class="line">template&lt; typename t0 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0 ) const ;</div>
<div class="line"><br /></div>
<div class="line">// EnableIf rank == 2 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1 ) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 3 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2 ) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 4 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 5 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 , typename t4 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const t4 &amp; i4</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 6 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 , typename t4 , typename t5 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const t4 &amp; i4</div>
<div class="line">, const t5 &amp; i5</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 7 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 , typename t4 , typename t5 , typename t6 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const t4 &amp; i4</div>
<div class="line">, const t5 &amp; i5</div>
<div class="line">, const t6 &amp; i6</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 8 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 , typename t4 , typename t5 , typename t6 , typename t7 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const t4 &amp; i4</div>
<div class="line">, const t5 &amp; i5</div>
<div class="line">, const t6 &amp; i6</div>
<div class="line">, const t7 &amp; i7</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 9 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 , typename t4 , typename t5 , typename t6 , typename t7 , typename t8 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const t4 &amp; i4</div>
<div class="line">, const t5 &amp; i5</div>
<div class="line">, const t6 &amp; i6</div>
<div class="line">, const t7 &amp; i7</div>
<div class="line">, const t8 &amp; i8</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 10 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 , typename t4 , typename t5 , typename t6 , typename t7 , typename t8 , typename t9 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const t4 &amp; i4</div>
<div class="line">, const t5 &amp; i5</div>
<div class="line">, const t6 &amp; i6</div>
<div class="line">, const t7 &amp; i7</div>
<div class="line">, const t8 &amp; i8</div>
<div class="line">, const t9 &amp; i9</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">//--------------------</div>
<div class="line">// Member access (improper):</div>
<div class="line"><br /></div>
<div class="line">// EnableIf rank == 0 and i# == 0</div>
<div class="line">reference operator()( const int i0</div>
<div class="line-block">
<div class="line">, const int i1 = 0</div>
<div class="line">, const int i2 = 0</div>
<div class="line">, const int i3 = 0</div>
<div class="line">, const int i4 = 0</div>
<div class="line">, const int i5 = 0</div>
<div class="line">, const int i6 = 0</div>
<div class="line">, const int i7 = 0</div>
<div class="line">, const int i8 = 0</div>
<div class="line">, const int i9 = 0</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 1 and std::is_integral&lt;t0&gt;::value and i{1-9} == 0</div>
<div class="line">template&lt; typename t0 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const int i1</div>
<div class="line">, const int i2 = 0</div>
<div class="line">, const int i3 = 0</div>
<div class="line">, const int i4 = 0</div>
<div class="line">, const int i5 = 0</div>
<div class="line">, const int i6 = 0</div>
<div class="line">, const int i7 = 0</div>
<div class="line">, const int i8 = 0</div>
<div class="line">, const int i9 = 0</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 2 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const int i2</div>
<div class="line">, const int i3 = 0</div>
<div class="line">, const int i4 = 0</div>
<div class="line">, const int i5 = 0</div>
<div class="line">, const int i6 = 0</div>
<div class="line">, const int i7 = 0</div>
<div class="line">, const int i8 = 0</div>
<div class="line">, const int i9 = 0</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 3 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const int i3</div>
<div class="line">, const int i4 = 0</div>
<div class="line">, const int i5 = 0</div>
<div class="line">, const int i6 = 0</div>
<div class="line">, const int i7 = 0</div>
<div class="line">, const int i8 = 0</div>
<div class="line">, const int i9 = 0</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 4 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const int i4</div>
<div class="line">, const int i5 = 0</div>
<div class="line">, const int i6 = 0</div>
<div class="line">, const int i7 = 0</div>
<div class="line">, const int i8 = 0</div>
<div class="line">, const int i9 = 0</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 5 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 , typename t4 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const t4 &amp; i4</div>
<div class="line">, const int i5</div>
<div class="line">, const int i6 = 0</div>
<div class="line">, const int i7 = 0</div>
<div class="line">, const int i8 = 0</div>
<div class="line">, const int i9 = 0</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 6 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 , typename t4 , typename t5 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const t4 &amp; i4</div>
<div class="line">, const t5 &amp; i5</div>
<div class="line">, const int i6</div>
<div class="line">, const int i7 = 0</div>
<div class="line">, const int i8 = 0</div>
<div class="line">, const int i9 = 0</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 7 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 , typename t4 , typename t5 , typename t6 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const t4 &amp; i4</div>
<div class="line">, const t5 &amp; i5</div>
<div class="line">, const t6 &amp; i6</div>
<div class="line">, const int i7</div>
<div class="line">, const int i8 = 0</div>
<div class="line">, const int i9 = 0</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 8 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 , typename t4 , typename t5 , typename t6 , typename t7 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const t4 &amp; i4</div>
<div class="line">, const t5 &amp; i5</div>
<div class="line">, const t6 &amp; i6</div>
<div class="line">, const t7 &amp; i7</div>
<div class="line">, const int i8</div>
<div class="line">, const int i9 = 0</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">// EnableIf rank == 9 and std::is_integral&lt;t#&gt;::value</div>
<div class="line">template&lt; typename t0 , typename t1 , typename t2 , typename t3 , typename t4 , typename t5 , typename t6 , typename t7 , typename t8 &gt;</div>
<div class="line">reference operator()( const t0 &amp; i0</div>
<div class="line-block">
<div class="line">, const t1 &amp; i1</div>
<div class="line">, const t2 &amp; i2</div>
<div class="line">, const t3 &amp; i3</div>
<div class="line">, const t4 &amp; i4</div>
<div class="line">, const t5 &amp; i5</div>
<div class="line">, const t6 &amp; i6</div>
<div class="line">, const t7 &amp; i7</div>
<div class="line">, const t8 &amp; i8</div>
<div class="line">, const int i9</div>
<div class="line">) const ;</div>
<div class="line"><br /></div>
</div>
<div class="line">//--------------------</div>
<div class="line">// Construct/copy/destroy:</div>
<div class="line"><br /></div>
<div class="line">~view();</div>
<div class="line">constexpr view();</div>
<div class="line">constexpr view( const view &amp; );</div>
<div class="line">constexpr view( view &amp;&amp; );</div>
<div class="line">view &amp; operator = ( const view &amp; );</div>
<div class="line">view &amp; operator = ( view &amp;&amp; );</div>
<div class="line"><br /></div>
<div class="line">constexpr view( pointer</div>
<div class="line-block">
<div class="line">, size_t implicit_N0 = 0</div>
<div class="line">, size_t implicit_N1 = 0</div>
<div class="line">, size_t implicit_N2 = 0</div>
<div class="line">, size_t implicit_N3 = 0</div>
<div class="line">, size_t implicit_N4 = 0</div>
<div class="line">, size_t implicit_N5 = 0</div>
<div class="line">, size_t implicit_N6 = 0</div>
<div class="line">, size_t implicit_N7 = 0</div>
<div class="line">, size_t implicit_N8 = 0</div>
<div class="line">, size_t implicit_N9 = 0</div>
<div class="line">);</div>
<div class="line"><br /></div>
</div>
<div class="line">template&lt; class UType , class ... UProperties &gt;</div>
<div class="line">constexpr view( const view&lt; UType , UProperties ... &gt; &amp; );</div>
<div class="line"><br /></div>
<div class="line">template&lt; class UType , class ... UProperties &gt;</div>
<div class="line">view &amp; operator = ( const view&lt; UType , UProperties ... &gt; &amp; );</div>
</div>
<div class="line">};</div>
<div class="line"><br /></div>
<div class="line">}}</div>
</div>
</blockquote>
<p><strong>using value_type = typename std::remove_all_extents&lt; DataType &gt;::type ;</strong></p>
<p><strong>using reference =</strong></p>
<blockquote>
The type returned by a dereferencing operator.  Typically this will be <strong>value_type &amp;</strong>.
[Note: The reference type may be a proxy depending upon the <strong>Properties</strong>.
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>static constexpr unsigned rank() const</strong></p>
<blockquote>
Returns: The rank of the viewed array.</blockquote>
<p><strong>template&lt; typename IntegralType &gt; constexpr size_t extent( const IntegralType &amp; r ) const</strong></p>
<blockquote>
Returns: The exent of dimension r when <tt class="docutils literal">r &lt; rank()</tt>
and 1 when ( <strong>rank</strong> &lt;= r &lt; <em>rank upper bound</em> ).
A default constructed view will have extent(r) == 0
for all implicit dimensions.
The return value of an explicit dimension queried with a literal input value must be &quot;constexpr&quot; observable.</blockquote>
<p><strong>constexpr size_t size() const</strong></p>
<blockquote>
Returns: The product of the extents.</blockquote>
<p><strong>using layout =</strong></p>
<blockquote>
The layout type property that defaults to <strong>void</strong>.</blockquote>
<p><strong>using is_regular = std::integral_constant&lt;bool,</strong> <em>B</em> <strong>&gt;</strong></p>
<blockquote>
Denoting by <strong>is_regular::value</strong> 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; constexpr size_t stride( const IntegralType &amp; r ) const</strong></p>
<blockquote>
<p>Requires: is_regular::value</p>
<p>Returns:  The distance between members when index <strong>r</strong> is incremented by one.
If is_regular::value == false the return value is undefined.</p>
</blockquote>
<p><strong>constexpr size_t span() const</strong></p>
<blockquote>
<p>Returns:  A distance that is at least one plus the
maximum distance between any two members of the array.</p>
<p>Remark: For a one-to-one layout mapping the span will equal the size.</p>
</blockquote>
<p><strong>static constexpr
size_t span( size_t implicit_N0 , size_t implicit_N1 = 0 , size_t implicit_N2 = 0 ,
size_t implicit_N3 = 0 , size_t implicit_N4 = 0 , size_t implicit_N5 = 0 ,
size_t implicit_N6 = 0 , size_t implicit_N7 = 0 , size_t implicit_N8 = 0 ,
size_t implicit_N9 = 0 )</strong></p>
<blockquote>
Returns:  The span of the view if it were constructed with the implicit dimensions.</blockquote>
<p><strong>constexpr pointer data() const</strong></p>
<blockquote>
<p>Returns: Pointer to the member with the minimum location.</p>
<p>Requires: All members are in the range <tt class="docutils literal">[ data() .. data() + span() )</tt>.</p>
</blockquote>
<p><strong>reference operator()() const</strong></p>
<blockquote>
<p>Requires rank == 0.</p>
<p>Returns:  A reference to the member of a rank zero array.</p>
<p>Remark: It is recommended that the requirement be enforced by conditionally
defining the return type of the operator.</p>
</blockquote>
<pre class="code c++ literal-block">
<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">rank</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">0</span> <span class="punctuation">,</span> <span class="name">reference</span>
                         <span class="punctuation">,</span> <span class="name">error_tag_invalid_access_to_non_rank_zero_view</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>
</pre>
<!--  -->
<p><strong>template&lt; typename IntegralType &gt; reference operator[]( const IntegralType &amp; i ) const</strong></p>
<blockquote>
<div class="line-block">
<div class="line">Requires: rank() == 1</div>
<div class="line">Requires: is_integral&lt;IntegralType&gt;::value</div>
<div class="line">Requires: 0 &lt;= i &lt; extent_0()</div>
</div>
<p>Returns: Reference to member denoted by index <strong>i</strong>.</p>
<p>Remark:  A view with a bounds-checking property should throw <strong>std::out_of_range</strong>
when the index bounds requirement is violated.</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="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">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="punctuation">;</span>
</pre>
<!--  -->
<div class="line-block">
<div class="line"><strong>template&lt; typename t0 , typename t1 , ... , typename tm &gt;</strong></div>
<div class="line"><strong>reference operator()( const t0 &amp; i0 , const t1 &amp; i1 , ... , const tm &amp; im ) const</strong></div>
</div>
<blockquote>
<div class="line-block">
<div class="line">Requires:  std::is_integral&lt;t#&gt;::value</div>
<div class="line">Requires:  For a <em>proper</em> deference operator rank() == m + 1</div>
<div class="line">Requires:  For an <em>improper*</em> deference operator rank() &lt;= m</div>
<div class="line">Requires:  0 &lt;= i# &lt; extent_#()</div>
</div>
<p>Returns: Reference to member associated with multi-index (i0,i1,...,im).</p>
<p>Remark: Index arguments are accepted as constant references of a
template type to defer type promotion of these arguments until
they appear in the layout mapping computation.
This has been demonstrated to better enable conventional compilers to
optimize code containting the layout mapping computation without the
need for specialized pattern recognition of <strong>view::operator()</strong>.</p>
<p>Remark:  The <em>improper</em> dereference operator is a necessary usability feature
to allow functions to accept views of variable rank.</p>
<p>Remark:  A view with a bounds-checking property should throw <strong>std::out_of_range</strong>
when the index bounds requirement is violated.
Note that for improper dereference operator extent_#() == 1 when rank() &lt;= #.</p>
<p>Remark:  It is recommended that the rank and type requirements be enforced by
conditionally enabling the operators.</p>
</blockquote>
<pre class="code c++ literal-block">
<span class="comment single">// Proper rank 4 member access operator
</span><span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">t0</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">t1</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">t2</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">t3</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">t4</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">rank</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">4</span> <span class="operator">&amp;&amp;</span>
                         <span class="name">std</span><span class="operator">::</span><span class="name">is_integral</span><span class="operator">&lt;</span><span class="name">t0</span><span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">&amp;&amp;</span>
                         <span class="name">std</span><span class="operator">::</span><span class="name">is_integral</span><span class="operator">&lt;</span><span class="name">t1</span><span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">&amp;&amp;</span>
                         <span class="name">std</span><span class="operator">::</span><span class="name">is_integral</span><span class="operator">&lt;</span><span class="name">t2</span><span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">&amp;&amp;</span>
                         <span class="name">std</span><span class="operator">::</span><span class="name">is_integral</span><span class="operator">&lt;</span><span class="name">t3</span><span class="operator">&gt;::</span><span class="name">value</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">t0</span> <span class="operator">&amp;</span> <span class="name">i0</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="name">t1</span> <span class="operator">&amp;</span> <span class="name">i1</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="name">t2</span> <span class="operator">&amp;</span> <span class="name">i2</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="name">t3</span> <span class="operator">&amp;</span> <span class="name">i3</span>
           <span class="punctuation">)</span> <span class="keyword">const</span> <span class="punctuation">;</span>

<span class="comment single">// Improper rank 4 member access operator
</span><span class="keyword">template</span><span class="operator">&lt;</span> <span class="keyword">typename</span> <span class="name">t0</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">t1</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">t2</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">t3</span> <span class="punctuation">,</span> <span class="keyword">typename</span> <span class="name">t4</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">rank</span><span class="punctuation">()</span> <span class="operator">==</span> <span class="literal number integer">4</span> <span class="operator">&amp;&amp;</span>
                         <span class="name">std</span><span class="operator">::</span><span class="name">is_integral</span><span class="operator">&lt;</span><span class="name">t0</span><span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">&amp;&amp;</span>
                         <span class="name">std</span><span class="operator">::</span><span class="name">is_integral</span><span class="operator">&lt;</span><span class="name">t1</span><span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">&amp;&amp;</span>
                         <span class="name">std</span><span class="operator">::</span><span class="name">is_integral</span><span class="operator">&lt;</span><span class="name">t2</span><span class="operator">&gt;::</span><span class="name">value</span> <span class="operator">&amp;&amp;</span>
                         <span class="name">std</span><span class="operator">::</span><span class="name">is_integral</span><span class="operator">&lt;</span><span class="name">t3</span><span class="operator">&gt;::</span><span class="name">value</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">t0</span> <span class="operator">&amp;</span> <span class="name">i0</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="name">t1</span> <span class="operator">&amp;</span> <span class="name">i1</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="name">t2</span> <span class="operator">&amp;</span> <span class="name">i2</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="name">t3</span> <span class="operator">&amp;</span> <span class="name">i3</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="keyword type">int</span> <span class="name">i4</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="keyword type">int</span> <span class="name">i5</span> <span class="operator">=</span> <span class="literal number integer">0</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="keyword type">int</span> <span class="name">i6</span> <span class="operator">=</span> <span class="literal number integer">0</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="keyword type">int</span> <span class="name">i7</span> <span class="operator">=</span> <span class="literal number integer">0</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="keyword type">int</span> <span class="name">i8</span> <span class="operator">=</span> <span class="literal number integer">0</span>
           <span class="punctuation">,</span> <span class="keyword">const</span> <span class="keyword type">int</span> <span class="name">i9</span> <span class="operator">=</span> <span class="literal number integer">0</span>
           <span class="punctuation">)</span> <span class="keyword">const</span> <span class="punctuation">;</span>
</pre>
<!--  -->
<p><strong>constexpr view()</strong></p>
<blockquote>
Effect: Construct a <em>null</em> view with extent_#() == 0 for all implicit dimensions
and data() == nullptr.</blockquote>
<p><strong>constexpr view( const view &amp; rhs )</strong></p>
<blockquote>
<p>Effect: Construct a view of the array viewed by <strong>rhs</strong>.</p>
<p>Remark: There may be other <em>property</em> dependent effects.</p>
</blockquote>
<p><strong>view &amp; operator = ( const view &amp; rhs )</strong></p>
<blockquote>
<p>Effect: Assigns <strong>this</strong> to view the array viewed by <strong>rhs</strong>.</p>
<p>Remark: There may be other <em>property</em> dependent effects.</p>
</blockquote>
<p><strong>constexpr view( view &amp;&amp; rhs )</strong></p>
<blockquote>
<p>Effect: Construct a view of the array viewed by <strong>rhs</strong> and then <strong>rhs</strong> is <em>null</em> view.</p>
<p>Remark: There may be other <em>property</em> dependent effects.</p>
</blockquote>
<p><strong>view &amp; operator = ( view &amp;&amp; rhs )</strong></p>
<blockquote>
<p>Effect: Assigns <strong>this</strong> to view the array viewed by <strong>rhs</strong> then assigns <strong>rhs</strong> to be a <em>null</em> view.</p>
<p>Remark: There may be other <em>property</em> dependent effects.</p>
</blockquote>
<p><strong>~view()</strong></p>
<blockquote>
<p>Effect: Assigns <strong>this</strong> to be a <em>null</em> view.</p>
<p>Remark: There may be other <em>property</em> dependent effects.</p>
</blockquote>
<p><strong>constexpr view( pointer ptr , size_t implicit_N0 = 0 , size_t implicit_N1 = 0 , size_t implicit_N2 = 0 , size_t implicit_N3 = 0 , size_t implicit_N4 = 0 , size_t implicit_N5 = 0 , size_t implicit_N6 = 0 , size_t implicit_N7 = 0 , size_t implicit_N8 = 0 , size_t implicit_N9 = 0 );</strong></p>
<blockquote>
<p>Requires: The input <strong>ptr</strong> references memory <tt class="docutils literal">[ ptr .. ptr + S )</tt>
where S = <strong>view::span(implicit_N0,implicit_N1,...,implicit_N9)</strong>.</p>
<p>Effects: The <em>wrapping constructor*</em> constructs a multidimensional array view 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; class UType , class ... UProperties &gt; constexpr view( const view&lt; UType , UProperties ... &gt; &amp; rhs )</strong></p>
<blockquote>
<p>Requires: This view type is assignable to the <strong>rhs</strong> view type.
View assignability includes compatibility of the value type, dimensions, and properties.</p>
<p>Effect: Constructs a view of the array viewed by <strong>rhs</strong>.</p>
</blockquote>
<pre class="code c++ literal-block">
<span class="name">view</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="name">view</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">y</span><span class="punctuation">(</span> <span class="name">x</span> <span class="punctuation">);</span> <span class="comment single">// OK: compatible const from non-const and implicit from explicit dimension
</span><span class="name">view</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][]</span> <span class="operator">&gt;</span>       <span class="name">z</span><span class="punctuation">(</span> <span class="name">y</span> <span class="punctuation">);</span> <span class="comment single">// Error: cannot assign non-const from const</span>
</pre>
<!--  -->
<p><strong>template&lt; class UType , class ... UProperties &gt; view &amp; operator = ( const view&lt; UType , UProperties ... &gt; &amp; rhs )</strong></p>
<blockquote>
<p>Requires: This view type is assignable to the <strong>rhs</strong> view type.</p>
<p>Effect: Assigns <strong>this</strong> to view the array viewed by <strong>rhs</strong>.</p>
</blockquote>
</div>
<div class="section" id="view-properties-dimension-and-array-view">
<h1>13&nbsp;&nbsp;&nbsp;View Properties: Dimension and <strong>array_view</strong></h1>
<blockquote>
<div class="line-block">
<div class="line">namespace std {</div>
<div class="line">namespace experimental {</div>
<div class="line">namespace view_property {</div>
<div class="line"><br /></div>
<div class="line">// Specify all implicit dimensions of a given rank</div>
<div class="line">template&lt; unsigned Rank &gt;</div>
<div class="line">struct implicit_dimensions ;</div>
<div class="line"><br /></div>
<div class="line">// If relaxed array dimension syntax is unavailable</div>
<div class="line">template&lt; size_t , size_t , size_t , size_t , size_t</div>
<div class="line-block">
<div class="line">, size_t , size_t , size_t , size_t , size_t &gt;</div>
</div>
<div class="line">struct dimension ;</div>
<div class="line"><br /></div>
<div class="line">}}}</div>
<div class="line"><br /></div>
<div class="line">// For compatibility with declaration syntax of previous array_view proposal</div>
<div class="line"><br /></div>
<div class="line">namespace std {</div>
<div class="line">namespace experimental {</div>
<div class="line"><br /></div>
<div class="line">template&lt; typename T , unsigned Rank &gt;</div>
<div class="line">using array_view = typename view&lt;T,view_property::implicit_dimensions&lt;Rank&gt; &gt; ;</div>
<div class="line"><br /></div>
<div class="line">}}</div>
</div>
</blockquote>
</div>
<div class="section" id="assignability-of-views-of-non-identical-types">
<h1>14&nbsp;&nbsp;&nbsp;Assignability of Views of Non-identical Types</h1>
<p>It is essential that view of non-identical, compatible types be assignable.
For example:</p>
<pre class="code c++ literal-block">
<span class="name">view</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="name">view</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">y</span><span class="punctuation">(</span> <span class="name">x</span> <span class="punctuation">);</span> <span class="comment single">// valid assignment</span>
</pre>
<!--  -->
<p>The 'std::is_assignable' meta-function must be partial specialized to
implement the view 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">view</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">view</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">view</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">view</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">view</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">view</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 impplicit.
</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 view's data.
For example,
1. implicitly dimensioned views are assignable from equal rank explicitly dimensioned views,
2. strided layout views with implicit dimensions are assignable from equal rank views with regular layout, or
3. a view with an access intent property, such as <em>random</em> or <em>restrict</em> may be assigned from a view without such a property.</p>
</div>
<div class="section" id="subview-of-view">
<h1>15&nbsp;&nbsp;&nbsp;Subview of View</h1>
<p>The capability to <strong>easily</strong> extract subviews of a view, or subviews of subviews,
is essential for usability.
Non-trivial subviews of regular views will often have <strong>view_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">view</span><span class="operator">&lt;</span> <span class="keyword type">int</span><span class="punctuation">[][][]</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">subview</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">subview</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 subview 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">subview</span><span class="punctuation">(</span> <span class="name">x</span> <span class="punctuation">,</span> <span class="name">view_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>Subview types are generated with a meta-function.</p>
<blockquote>
<div class="line-block">
<div class="line">namespace std {</div>
<div class="line">namespace experimental {</div>
<div class="line">namespace view_property {</div>
<div class="line"><br /></div>
<div class="line">template&lt; typename ViewType , class ... Indices_And_Ranges &gt;</div>
<div class="line">struct subview_type ;</div>
<div class="line"><br /></div>
<div class="line">struct all_type {};</div>
<div class="line">constexpr all_type all = all_type();</div>
<div class="line"><br /></div>
<div class="line">}}}</div>
<div class="line"><br /></div>
<div class="line">namespace std {</div>
<div class="line">namespace experimental {</div>
<div class="line"><br /></div>
<div class="line">template&lt; typename ViewType , class ... Indices_And_Ranges &gt;</div>
<div class="line">using subview_t = typename view_property::subview_type&lt; ViewType , Indices_And_Ranges &gt;::type ;</div>
<div class="line"><br /></div>
<div class="line">template&lt; typename DataType , class ... Parameters , class ... Indices_And_Ranges &gt;</div>
<div class="line">subview_t&lt; view&lt; DataType, Parameters ... &gt; , Indices_And_Ranges ... &gt;</div>
<div class="line">subview( const view&lt; DataType, Parameters ... &gt; &amp; , Indices_And_Ranges ... );</div>
<div class="line"><br /></div>
<div class="line">template&lt; typename T &gt;</div>
<div class="line">struct is_integral_range ;</div>
<div class="line"><br /></div>
<div class="line">}}</div>
</div>
</blockquote>
<p><strong>template&lt; typename T &gt; struct is_integral_range : public integral_constant&lt;bool,</strong><em>F</em><strong>&gt;</strong></p>
<blockquote>
Returns: Meta function indicating whether T is an integral range.</blockquote>
<p><strong>template&lt; typename ViewType , class ... Indices_And_Ranges &gt; struct subview_type ;</strong></p>
<blockquote>
<div class="line-block">
<div class="line">Requires:  ViewType::rank() == sizeof...(Indices_And_Ranges)</div>
<div class="line">Requires:  Each parameter in Indices_And_Ranges is either is_integral&lt;T&gt; or is_integral_range&lt;T&gt;.</div>
</div>
<p>Returns: The view type of the subview from the input view and parameter pack of indices and integral ranges.
The rank of the subview is equal to the number of integral ranges in the parameter pack.
When a dimension of the source <strong>ViewType</strong> is explicit and the corresponding range argument is <strong>all</strong> then the dimension of the resulting view type is explicit and equal to the source dimension</p>
</blockquote>
</div>
<div class="section" id="limited-iterator-interface">
<h1>16&nbsp;&nbsp;&nbsp;Limited iterator interface</h1>
<p>A <strong>view</strong> may have a non-isomorphic mapping between its
multi-index space (domain) and span of member memory (range).
For example, a subview or dimension padded view will be
non-isomorphic.
An iterator for the members of a non-isomorphic view 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 view 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>view&lt;T[]&gt;</strong> will have <strong>begin</strong> and <strong>end</strong> overloads.</p>
<blockquote>
<div class="line-block">
<div class="line">namespace std {</div>
<div class="line"><br /></div>
<div class="line">template&lt; class T , class ...P &gt;</div>
<div class="line">typename std::enable_if&lt; <em>(rank one and isomorphic layout and no incompatible access intent properties)</em> , typename view&lt;T,P...&gt;::pointer &gt;::type</div>
<div class="line">begin( const std::experimental::view&lt;T,P...&gt; &amp; v )</div>
<div class="line">{ return v.data(); }</div>
<div class="line"><br /></div>
<div class="line">template&lt; class T , class ...P &gt;</div>
<div class="line">typename std::enable_if&lt; <em>(rank one and isomorphic layout and no incompatible access intent properties)</em> , typename view&lt;T,P...&gt;::pointer &gt;::type</div>
<div class="line">end( const std::experimental::view&lt;T,P...&gt; &amp; v )</div>
<div class="line">{ return v.data() + v.size(); }</div>
<div class="line"><br /></div>
<div class="line">}</div>
</div>
</blockquote>
<p>Note that in the more general case of an isomorphic view
of any rank a pointer (iterator) range for view 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">view</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">view</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">view</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="view-property-member-access-array-bounds-checking">
<h1>17&nbsp;&nbsp;&nbsp;View Property : Member Access Array Bounds Checking</h1>
<blockquote>
<div class="line-block">
<div class="line">namespace std {</div>
<div class="line">namespace experimental {</div>
<div class="line">namespace view_property {</div>
<div class="line">struct bounds_checking ;</div>
<div class="line">}}}</div>
</div>
</blockquote>
<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 signficant overhead that impedes the debugging process.
A member access array bounds checking view 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 views.
</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">view_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">view</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="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 a view 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 <strong>std::out_of_range</strong> is thrown.</p>
</div>
</div>
</body>
</html>
