<!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">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title>Contiguous Ranges</title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; position: absolute; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
  { position: relative; }
pre.numberSource a.sourceLine:empty
  { position: absolute; }
pre.numberSource a.sourceLine::before
  { content: attr(data-line-number);
    position: absolute; left: -5em; text-align: right; vertical-align: baseline;
    border: none; pointer-events: all;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
    color: #aaaaaa;
  }
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
div.sourceCode
  {  }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  </style>
  <style type="text/css">
  ins {
    color:#009a9a; text-decoration:underline;
  }
  
  del {
    color:red; text-decoration:line-through;
  }
  
  ednote {
    color:blue;
  }
  
  table {
    border-collapse: collapse;
  }
  
  table, th, td {
    border: 1px solid black;
  }
  
  code.diff > span.st {
    color: darkred;
  }
  </style>
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="607">
  <tr>
    <td width="172" align="left" valign="top">Document number:</td>
    <td width="435">
      P0944R0
    </td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Date:</td>
    <td width="435">2018-02-11</td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Project:</td>
    <td width="435">C++ Extensions for Ranges, Library Evolution Working Group</td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Reply-to:</td>
    <td width="435">
      Casey Carter &lt;<a href="mailto:Casey@Carter.net">Casey@Carter.net</a>&gt;<br>
    </td>
  </tr>
</table>
<div id="header">
<h1 class="title">Contiguous Ranges</h1>
</div>
<h1>Synopsis</h1>
<p>This paper proposes extensions to ISO/IEC TS 21425:2017 “C++ Extensions for ranges” (The “Ranges TS”) to enable first-class support for contiguous iterators and contiguous ranges. Contiguity of storage is a critical property of data which the Ranges design should be able to communicate to generic algorithms.</p>
<h1>Background</h1>
<p>The C++ standard library has been slowly recognizing the increasing importance of data contiguity. The word “contiguous” does not appear in the C++98 standard library specification. Nevertheless:</p>
<ul>
<li><p><code>valarray</code> was implicitly required to store elements contiguously per [lib.valarray.access]/3:</p>
<blockquote>
<p>The expression <code>&amp;a[i + j] == &amp;a[i] + j</code> evaluates as <code>true</code> for all <code>size_t i</code> and <code>size_t j</code> such that <code>i+j</code> is less than the length of the non-constant array <code>a</code>.&quot;</p>
</blockquote></li>
<li><p>In those days a quality implementation was expected to implement <code>vector</code> (not <code>vector&lt;bool&gt;</code>) using contiguous memory despite that property not being required. Even in the “dark ages” of the late 1990s we understood the interaction of contiguous storage with caches; hence the exhortation in [lib.sequence.reqmts]/2 “<code>vector</code> is the type of sequence that should be used by default.”</p></li>
</ul>
<p>As a Technical Corrigendum, C++03 made very few changes. One of those changes was to promote the contiguity of <code>vector&lt;not_bool&gt;</code> from QoI to a requirement in [lib.vector]/1:</p>
<blockquote>
<p>The elements of a vector are stored contiguously, meaning that if <code>v</code> is a <code>vector&lt;T, Allocator&gt;</code> where <code>T</code> is some type other than <code>bool</code>, then it obeys the identity <code>&amp;v[n] == &amp;v[0] + n</code> for all <code>0 &lt;= n &lt; v.size()</code>. Presumably five more years of studying the interactions of contiguity with caching made it clear to WG21 that contiguity needed to be mandated and non-contiguous <code>vector</code> implementation should be clearly banned.</p>
</blockquote>
<p>Eight more years of processor speed increasing faster than memory latency made cache effects even more pronounced in the C++11 era. The standard library responded by adding more support for contiguity: <code>basic_string</code> added a requirement for contiguous storage, the new <code>std::array</code> sprang into existence with contiguous storage, and a new library function <code>std::align</code> was added to help users parcel out aligned chunks of contiguous memory from large blocks of storage.</p>
<p>C++17 recognized that pointers are members of a larger class of contiguous iterators. <a href="https://wg21.link/n4284">N4284 “Contiguous iterators”</a> defined the terms “contiguous iterator” [iterator.requirements.general]/6:</p>
<blockquote>
<p>Iterators that further satisfy the requirement that, for integral values <code>n</code> and dereferenceable iterator values <code>a</code> and <code>(a + n)</code>, <code>*(a + n)</code> is equivalent to <code>*(addressof(*a) + n)</code>, are called <em>contiguous iterators</em>. and “contiguous container” [container.requirements.general]/13: A <em>contiguous container</em> is a container that supports random access iterators and whose member types <code>iterator</code> and <code>const_iterator</code> are contiguous iterators.</p>
</blockquote>
<p>Sadly, C++17 fell short of providing the tools necessary to make contiguous iterators usable in generic contexts. There is a set of concrete iterator types that are specified to be contiguous iterators, but there is no general mechanism in C++17 to determine if a given iterator type is a contiguous iterator. It is notable that <a href="https://wg21.link/n3884">N3884 “Contiguous Iterators: a refinement of random access iterators”</a> <em>did</em> try to provide such a facility in the form of a new iterator tag <code>contiguous_iterator_tag</code>. LEWG rejected the new category tag in Issaquah 2014 out of fear that too much code would be broken by changing the iterator category of the existing contiguous iterators from <code>random_access_iterator_tag</code> to <code>contiguous_iterator_tag</code>. LEWG requested a new type trait be used to distinguish contiguous iterators. <a href="https://wg21.link/n4183">N4183 “Contiguous Iterators: Pointer Conversion &amp; Type Trait”</a> presented such a trait, but that proposal seems to have been regarded with indifference by LEWG.</p>
<p>This paper does not motivate the need for contiguous ranges, or for generic algorithms that work with contiguous ranges. The treatment in N3884 is sufficient.</p>
<h2>Proposed Design</h2>
<p>This paper proposes to take advantage of the opportunity provided by the distinct mechanisms in the Ranges TS to both leave the iterator category of the standard library’s contiguous iterators unchanged <em>and</em> update the category of those iterators to denote them as contiguous. In the Ranges TS design, the category of iterators is determined using the <code>ranges::iterator_category_t</code> alias and its backing class template <code>ranges::iterator_category</code> (Ranges TS [iterator.assoc.types.iterator_category]). This trait is notably distinct from <code>std::iterator_traits</code> that determines the category of Standard iterators. By defining the Ranges and Standard traits to different categories, “new” code that is Ranges-aware can detect contiguous iterators using <code>ranges::iterator_category_t</code>, while “old” code that may break if presented a category other than random access for for e.g. <code>vector::iterator</code> will use <code>std::iterator_traits</code> and be presented <code>std::random_access_iterator_tag</code>.</p>
<p>This paper also proposes that contiguous iterators are a refinement of random access iterators as did N3884. Since a contiguous range <code>[i, s)</code> (where <code>s</code> is a sentinel for <code>i</code>) must be equivalent to some pointer range <code>[p, n)</code> and random access is certainly possible in that pointer range, it is trivial to implement random access for any contiguous iterator. Allowing contiguous iterators that are not random access would not admit any additional models or increase the expressive power of the design.</p>
<p>Unlike the prior art, this paper does not propose a customization point to retrieve the pointer value that corresponds to some contiguous iterator value. This paper’s goal is to enable access to contiguous <em>ranges</em>, rather than provide mechanisms to handle individual contiguous iterators, and a sized contiguous range <code>rng</code> (or <code>[i, s)</code>) can always be converted to a pointer range <code>[data(rng), size(rng))</code> (resp. <code>[s - i ? addressof(*i) : nullptr, s - i)</code>). Implementation of generic algorithms that take advantage of contiguity does not require a facility to convert a “monopole” contiguous iterator to a pointer. The <code>copy</code> algorithm, for example, could be approximated with:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><a class="sourceLine" id="cb1-1" data-line-number="1"><span class="kw">template</span>&lt;InputIterator I, Sentinel&lt;I&gt; S, Iterator O&gt;</a>
<a class="sourceLine" id="cb1-2" data-line-number="2">requires IndirectlyCopyable&lt;I, O&gt;</a>
<a class="sourceLine" id="cb1-3" data-line-number="3"><span class="dt">void</span> copy(I i, S s, O o) {</a>
<a class="sourceLine" id="cb1-4" data-line-number="4">  <span class="cf">for</span> (; i != s; ++i, ++o) {</a>
<a class="sourceLine" id="cb1-5" data-line-number="5">    *o = *i;</a>
<a class="sourceLine" id="cb1-6" data-line-number="6">  }</a>
<a class="sourceLine" id="cb1-7" data-line-number="7">}</a>
<a class="sourceLine" id="cb1-8" data-line-number="8"></a>
<a class="sourceLine" id="cb1-9" data-line-number="9"><span class="kw">template</span>&lt;ContiguousIterator I, SizedSentinel&lt;I&gt; S, ContiguousIterator O&gt;</a>
<a class="sourceLine" id="cb1-10" data-line-number="10">requires IndirectlyCopyable&lt;I, O&gt; &amp;&amp;</a>
<a class="sourceLine" id="cb1-11" data-line-number="11">  Same&lt;<span class="dt">value_type_t</span>&lt;I&gt;, <span class="dt">value_type_t</span>&lt;O&gt;&gt; &amp;&amp;</a>
<a class="sourceLine" id="cb1-12" data-line-number="12">  is_trivially_copyable_v&lt;<span class="dt">value_type_t</span>&lt;O&gt;&gt;</a>
<a class="sourceLine" id="cb1-13" data-line-number="13"><span class="dt">void</span> copy(I i, S s, O o) {</a>
<a class="sourceLine" id="cb1-14" data-line-number="14">  <span class="cf">if</span> (s - i &gt; <span class="dv">0</span>) {</a>
<a class="sourceLine" id="cb1-15" data-line-number="15">    <span class="bu">std::</span>memmove(&amp;*o, &amp;*i, (s - i) * <span class="kw">sizeof</span>(<span class="dt">value_type_t</span>&lt;I&gt;));</a>
<a class="sourceLine" id="cb1-16" data-line-number="16">  }</a>
<a class="sourceLine" id="cb1-17" data-line-number="17">}</a></code></pre></div>
<h2>Implementation Experience</h2>
<p>A variant of this design has been implemented in <a href="https://github.com/caseycarter/cmcstl2">CMCSTL2, the reference implementation of the Ranges TS</a>, for several months.</p>
<h1>Technical Specification</h1>
<p>Wording relative to <a href="https://wg21.link/n4685">N4685, the Ranges TS Working Draft</a>.</p>
<p>Change the synopsis of header <code>&lt;experimental/ranges/iterator&gt;</code> in <a href="https://timsong-cpp.github.io/cppwp/ranges-ts/iterator.synopsis">[iterator.synopsis]</a> as follows:</p>
<blockquote>
<p><tt>  // [iterators.random.access], RandomAccessIterator:</tt><br /> <tt>  template &lt;class I&gt;</tt><br /> <tt>  concept bool RandomAccessIterator = <i>see below</i>;</tt><br /> <br /> <tt>  <ins>// [iterators.contiguous], ContiguousIterator:</ins></tt><br /> <tt>  <ins>template &lt;class I&gt;</ins></tt><br /> <tt>  <ins>concept bool ContiguousIterator = <i>see below</i>;</ins></tt><br /></p>
<p>[…]</p>
<p><tt>  // 9.6.3, iterator tags:</tt><br /> <tt>  struct output_iterator_tag { };</tt><br /> <tt>  struct input_iterator_tag { };</tt><br /> <tt>  struct forward_iterator_tag : input_iterator_tag { };</tt><br /> <tt>  struct bidirectional_iterator_tag : forward_iterator_tag { };</tt><br /> <tt>  struct random_access_iterator_tag : bidirectional_iterator_tag { };</tt><br /> <tt>  <ins>struct contiguous_iterator_tag : random_access_iterator_tag { };</ins></tt><br /></p>
</blockquote>
<p>Modify <a href="https://timsong-cpp.github.io/cppwp/ranges-ts/iterator.assoc.types.iterator_category#1">[iterator.assoc.types.iterator_category]/1</a> as follows:</p>
<blockquote>
<p>1 <code>iterator_category_t&lt;T&gt;</code> is implemented as if:</p>
<p>[…]</p>
<p><tt>template &lt;class T&gt;</tt><br /> <tt>struct iterator_category&lt;T*&gt;</tt><br /> <tt>  : enable_if&lt;is_object&lt;T&gt;::value, <del>random_access</del><ins>contiguous</ins>_iterator_tag&gt; { };</tt><br /></p>
<p>[…]</p>
</blockquote>
<p>Insert a new paragraph after <a href="https://timsong-cpp.github.io/cppwp/ranges-ts/iterator.assoc.types.iterator_category#3">[iterator.assoc.types.iterator_category]/3</a>:</p>
<blockquote>
<ins>
<p>-?- <code>iterator_category&lt;I&gt;::type</code> is <code>contiguous_iterator_tag</code> when <code>I</code> denotes:</ins></p>
<ins>
<ul>
<li>the member type <code>iterator</code> or <code>const_iterator</code> of a specialization of <code>std::basic_string</code> (ISO/IEC 14882:2014 [basic.string])</ins></li>
</ul>
<ins>
<ul>
<li>the member type <code>iterator</code> or <code>const_iterator</code> of a specialization of <code>std::array</code> (ISO/IEC 14882:2014 [array])</ins></li>
</ul>
<ins>
<ul>
<li>the member type <code>iterator</code> or <code>const_iterator</code> of a specialization of <code>std::vector</code> except for <code>std::vector&lt;bool&gt;</code> (ISO/IEC 14882:2014 [vector])</ins></li>
</ul>
<ins>
<ul>
<li>the type returned by the <code>std::valarray</code> overloads of <code>std::begin</code> and <code>std::end</code> (ISO/IEC 14882:2014 [valarray.range])</ins></li>
</ul>
<ins>
<p>[<em>Note:</em> Implementations of this document that also implement <code>basic_string_view</code> from ISO/IEC 14882:2017 are also encouraged to ensure that <code>iterator_category&lt;I&gt;::type</code> is <code>contiguous_iterator_tag</code> when <code>I</code> denotes the member type <code>iterator</code> or <code>const_iterator</code> of a specialization of <code>basic_string_view</code>.—<em>end note</em>]</p>
</blockquote>
<p>Add a new subclause immediately after <a href="https://timsong-cpp.github.io/cppwp/ranges-ts/iterators.random.access">[iterators.random.access]</a>:</p>
<blockquote>
<ins>
<p>9.3.?? Concept <code>ContiguousIterator</code> [iterator.contiguous]</ins></p>
<ins>
<p>The <code>ContiguousIterator</code> concept refines <code>RandomAccessIterator</code> and provides a guarantee that the denoted elements are stored contiguously in memory.</ins></p>
<ins>
<p><tt>template &lt;class I&gt;</tt></ins><br /> <ins><tt>concept bool ContiguousIterator =</tt></ins><br /> <ins><tt>  RandomAccessIterator&lt;I&gt; &amp;&amp;</tt></ins><br /> <ins><tt>  DerivedFrom&lt;iterator_category_t&lt;I&gt;, contiguous_iterator_tag&gt; &amp;&amp;</tt></ins><br /> <ins><tt>  is_lvalue_reference&lt;reference_t&lt;I&gt;&gt;::value &amp;&amp;</tt></ins><br /> <ins><tt>  Same&lt;value_type_t&lt;I&gt;, remove_cv_t&lt;remove_reference_t&lt;reference_t&lt;I&gt;&gt;&gt;&gt;;</tt></ins><br /></p>
<ins>
<p>Let <code>a</code> and <code>b</code> be a dereferenceable iterators of type <code>I</code> such that <code>b</code> is reachable from <code>a</code>. <code>ContiguousIterator&lt;I&gt;</code> is satisfied only if:</ins></p>
<ul>
<li><ins>
<code>addressof(*(a + (b - a))) == addressof(*a) + (b - a)</code></ins></li>
</ul>
</blockquote>
<p>Modify <a href="https://timsong-cpp.github.io/cppwp/ranges-ts/std.iterator.tags#1">[std.iterator.tags]/1</a> as follows:</p>
<blockquote>
<p>1 […] The category tags are: <code>input_iterator_tag</code>, <code>output_iterator_tag</code>, <code>forward_iterator_tag</code>, <code>bidirectional_iterator_tag</code><ins>,</ins> <del>and</del> random_access_iterator_tag<ins>, and <code>contiguous_iterator_tag</code></ins>. […]</p>
<p><tt>namespace std { namespace experimental { namespace ranges { inline namespace v1 {</tt><br /> <tt>  struct output_iterator_tag { };</tt><br /> <tt>  struct input_iterator_tag { };</tt><br /> <tt>  struct forward_iterator_tag : input_iterator_tag { };</tt><br /> <tt>  struct bidirectional_iterator_tag : forward_iterator_tag { };</tt><br /> <tt>  struct random_access_iterator_tag : bidirectional_iterator_tag { };</tt><br /> <tt>  <ins>struct contiguous_iterator_tag : random_access_iterator_tag { };</ins></tt><br /> <tt>}}}}</tt><br /></p>
</blockquote>
<p>Modify the synopsis of class template <code>reverse_iterator</code> in <a href="https://timsong-cpp.github.io/cppwp/ranges-ts/reverse.iterator">[reverse.iterator]</a> as follows:</p>
<blockquote>
<p>[…]<br /> <tt>template &lt;BidirectionalIterator I&gt;</tt><br /> <tt>class reverse_iterator {</tt><br /> <tt>public:</tt><br /> <tt>  using iterator_type = I;</tt><br /> <tt>  using difference_type = difference_type_t&lt;I&gt;;</tt><br /> <tt>  using value_type = value_type_t&lt;I&gt;;</tt><br /> <tt>  using iterator_category = <del>iterator_category_t&lt;I&gt;</del><ins><i>see below</i></ins>;</tt><br /></p>
</blockquote>
<p>Add a new paragraph following the synopsis:</p>
<blockquote>
<ins>
<p>-?- The member typedef-name <code>iterator_category</code> denotes <code>random_access_iterator_tag</code> if <code>ContiguousIterator&lt;I&gt;</code> is satisfied, and otherwise denotes the same type as <code>iterator_category_t&lt;I&gt;</code>.</ins></p>
</blockquote>
<p>Modify the synopsis of <code>&lt;experimental/ranges/range&gt;</code> in <a href="https://timsong-cpp.github.io/cppwp/ranges-ts/range.synopsis">[range.synopsis]</a> as follows:</p>
<blockquote>
<p>[…]</p>
<p><tt>  // 10.6.10, RandomAccessRange:</tt><br /> <tt>  template &lt;class T&gt;</tt><br /> <tt>  concept bool RandomAccessRange = <i>see below</i>;</tt><br /> <br /> <tt>  <ins>// 10.6.??, ContiguousRange:</ins></tt><br /> <tt>  <ins>template &lt;class T&gt;</ins></tt><br /> <tt>  <ins>concept bool ContiguousRange = <i>see below</i>;</ins></tt><br /> <tt>}}}}</tt><br /></p>
</blockquote>
<p>Modify <a href="https://timsong-cpp.github.io/cppwp/ranges-ts/range.primitives.data#1">[range.primitives.data/1]</a> as follows:</p>
<blockquote>
<p>[…]</p>
<p>(1.3) — Otherwise, <code>ranges::begin(E)</code> if it is a valid expression of pointer to object type.</p>
<p>(1.?) — <ins>Otherwise, if <code>ranges::begin(E)</code> is a valid expression whose type satisfies <code>ContiguousIterator</code>, <code>ranges::begin(E) == ranges::end(E) ? nullptr : addressof(*ranges::begin(E))</code>, except that <code>E</code> is evaluated only once.</ins></p>
<p>(1.4) — Otherwise, <code>ranges::data(E)</code> is ill-formed.</p>
<p>[…]</p>
</blockquote>
<p>Add a new subclause after <a href="https://timsong-cpp.github.io/cppwp/ranges-ts/ranges.random.access">[ranges.random.access]</a>:</p>
<blockquote>
<ins>
<p>10.6.?? Contiguous ranges [ranges.contiguous]</ins></p>
<ins>
<p>1 The <code>ContiguousRange</code> concept specifies requirements of a <code>RandomAccessRange</code> type for which <code>begin</code> returns a type that satisfies <code>ContiguousIterator</code> ([iterators.contiguous]).</p>
<p><tt><ins>template &lt;class R&gt;</ins></tt><br /> <tt><ins>concept bool ContiguousRange =</ins></tt><br /> <tt><ins>  Range&lt;R&gt; &amp;&amp; ContiguousIterator&lt;iterator_t&lt;R&gt;&gt; &amp;&amp;</ins></tt><br /> <tt><ins>  requires(R&amp; r) {</ins></tt><br /> <tt><ins>    ranges::data(r);</ins></tt><br /> <tt><ins>    requires Same&lt;decltype(ranges::data(r)), add_pointer_t&lt;reference_t&lt;iterator_t&lt;R&gt;&gt;&gt;&gt;;</ins></tt><br /> <tt><ins>  };</ins></tt><br /></p>
</blockquote>
</body>
</html>
