<html><head><meta charset="utf-8"><title>Proposing array_ref&lt;T&gt; and string_ref</title><style type="text/css">
body {color: #000000; background-color: #FFFFFF;}

del {text-decoration: line-through; color: #8B0040;}
ins {text-decoration: underline; color: #005100;}

pre > code:only-child {display: inline-block}
.example, .implementation, .extract {margin: 1em 2em;}
pre.implementation > code {border: thin solid #bbf; background-color: #eef; padding: 1ex}
pre.example > code {border: thin solid #daf; background-color: #f8eeff; padding: 1ex}

section.function {}
.attribute {margin-left: 2em}
.attribute dt {float: left; font-style: italic; padding-right: 1ex}
.attribute dd {margin-left: 0}

.docinfo {float: right}
.docinfo p {margin: 0; text-align:right; font-style: italic}

section {padding-left: 1em}
section header {margin-left: -1em}

h2, h3, h4, h5, h6 { margin-bottom: .75em }
p {margin-top: .5em; margin-bottom: .5em}
p:first-child, ul, ol {margin-top: 0}
dt:not(:first-child) {margin-top: .5em}
p, li, dd {max-width: 80ex}

figure {display: inline-block; margin: 1ex 1em;
        border: thin solid #f88; background-color: #eef; padding: 1ex}
figcaption + p { margin-top: 0 }
figure > p:last-child { margin-bottom:0 }
figure > * { margin-left: 1em }
figure > figcaption { margin-left: 0 }
figcaption { font-weight: bold }

div.example {display: inline-block; clear: both; margin-left: 1ex;
             border: thin solid #dfd; background-color: #f8f8f8; padding: 1ex}

div.note > *:first-child::before {content: "Note: "; display: inline; font-weight: bold}
div.note {display: inline-block; margin-left: 1ex; border: thin solid 8f8;
          padding: 1ex; background-color: #efe}

:target {background-color: #fed}
</style><script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script><script type="text/javascript">$(function() {
    var next_id = 0
    function find_id(node) {
        // Look down the first children of 'node' until we find one
        // with an id. If we don't find one, give 'node' an id and
        // return that.
        var cur = node[0];
        while (cur) {
            if (cur.id) return curid;
            if (cur.tagName == 'A' && cur.name)
                return cur.name;
            cur = cur.firstChild;
        };
        // No id.
        node.attr('id', 'gensection-' + next_id++);
        return node.attr('id');
    };

    // Put a table of contents in the #toc nav.

    // This is a list of <ol> elements, where toc[N] is the list for
    // the current sequence of <h(N+2)> tags. When a header of an
    // existing level is encountered, all higher levels are popped,
    // and an <li> is appended to the level
    var toc = [$("<ol/>")];
    $(':header').not('h1').each(function() {
        var header = $(this);
        // For each <hN> tag, add a link to the toc at the appropriate
        // level.  When toc is one element too short, start a new list
        var levels = {H2: 0, H3: 1, H4: 2, H5: 3, H6: 4};
        var level = levels[this.tagName];
        if (typeof level == 'undefined') {
            throw 'Unexpected tag: ' + this.tagName;
        }
        // Truncate to the new level.
        toc.splice(level + 1, toc.length);
        if (toc.length < level) {
            // Omit TOC entries for skipped header levels.
            return;
        }
        if (toc.length == level) {
            // Add a <ol> to the previous level's last <li> and push
            // it into the array.
            var ol = $('<ol/>')
            toc[toc.length - 1].children().last().append(ol);
            toc.push(ol);
        }
        var header_text = header.text();
        toc[toc.length - 1].append(
            $('<li/>').append($('<a href="#' + find_id(header) + '"/>')
                              .text(header_text)));
    });
    $('#toc').append(toc[0]);
})
</script></head><body><header><div class="docinfo"><p>Document number: N3334=12-0024</p><p>Date: <time pubdate="">2012-01-14</time></p><address><p>Jeffrey Yasskin &lt;<a href="mailto:jyasskin@google.com">jyasskin@google.com</a>&gt; </p><p>Source at <a href="http://code.google.com/p/cxx1y-array-string-ref/">http://code.google.com/p/cxx1y-array-string-ref/</a></p></address></div><h1>Proposing array_ref&lt;T&gt; and string_ref</h1></header><nav id="toc"></nav>
<section>
<header><h2><a name="index_1overview">Overview</a></h2></header>
<p>References to arrays and strings are very common in C++ programs, but often the callee doesn't care about the exact type of the object that owns the data. 3 things generally happen in this case:<ol>
<li>The callee picks a particular type—a <code>vector</code>, say—and insists that callers copy the data if it was originally in another format.</li><li>The callee takes two parameters—a pointer and a length—and reduces the readability and safety of calls and loses any helper functions the original type provided.</li><li>The callee is rewritten as a template and its implementation is moved to a header file. This can increase flexibility if the author takes the time to code to a weaker iterator concept, but it can also increase compile time and code size, and can even introduce bugs if the author misses an assumption that the argument's contents are contiguous.</li></ol>
</p><p>Google and LLVM have independently implemented two types to encapsulate this kind of argument. <a href="#classstd_1_1array__ref"><code>array_ref&lt;T&gt;</code> </a> is implicitly constructible from several standard array-like types and stores a contiguous range of addresses. It provides the subset of operations from <code>std::array&lt;&gt;</code> and <code>std::vector&lt;&gt;</code> that work on immutable sequences. Because <code><a href="#classstd_1_1array__ref">array_ref</a></code> stores pointers rather than a reference to the original array, it also supports a few operations to modify the current view.</p><p><a href="#classstd_1_1basic__string__ref"><code>string_ref</code> </a> is implicitly constructible from <code>const char*</code> and <code>std::string</code>. It provides most of the member operations from <code>std::string</code> to ease conversion. This paper follows <a href="http://src.chromium.org/viewvc/chrome/trunk/src/base/string_piece.h?view=markup">Chromium</a> in extending <code>string_ref</code> to <code><a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt;charT, traits&gt;</code> (Chromium omits <code>traits</code>). We provide typedefs to parallel the 4 <code>basic_string</code> typedefs.</p><p>Both Google's and LLVM's <code>string_ref</code> types extend the interface from <code>std::string</code> to provide some helpful utility functions:<ul>
<li><a href="#classstd_1_1basic__string__ref_1a2577f6f7b9d8b1c1121d06f84033fa66">starts_with </a></li><li><a href="#classstd_1_1basic__string__ref_1a726218a6f6faf10bad00bb9882d61a03">ends_with </a></li><li><a href="#classstd_1_1basic__string__ref_1aa5c42d285bc01c32eda9ec3e83a3a098">remove_prefix </a></li><li><a href="#classstd_1_1basic__string__ref_1accde94ea00561b9e8c38b6df879f7bc9">remove_suffix </a></li><li>split</li><li>trim</li><li>consume_prefix</li><li>count</li></ul>
</p><p>Versions of <code>std::string</code> operations that take <code>string_ref</code> instead also give the standard a way to provide in-place operations on non-null-terminated byte/character sequences:<ul>
<li>hash, as requested by c++std-lib-31935</li><li>numeric conversions</li></ul>
</p><p>Note that some of the code samples in this paper don't use full C++11 conventions because they're extracted from code that actually compiles, and current compilers don't yet support the whole C++11 language.</p></section>
<section>
<header><h2><a name="index_1inventions">Inventions in this paper</a></h2></header>
<p>Google's <code>StringPiece</code> provides <code>as_string</code> and <code>ToString</code> methods to convert to <code>std::string</code>. LLVM's <code>StringRef</code> provides both a <code>str()</code> explicit conversion and an implicit <code>operator std::string()</code>, and similarly for <code>ArrayRef</code> to <code>std::vector</code>. Since this paper builds on top of C++11, we provide <em><code>explicit</code></em> conversion operators in addition to two named conversions <code>vec()</code> and <code>str()</code>.</p><p>Google's and LLVM's <code>string_ref</code> types provide a subset of <code>std::string's</code> searching operations, but they do provide '<code>pos</code>' arguments to specify where to start the search. Because <code>string_ref::substr</code> is much cheaper than <code>string::substr</code>, this paper removes the <code>pos</code> argument entirely.</p><p>None of the existing classes have <code>constexpr</code> methods.</p></section>
<section>
<header><h2><a name="index_1bikeshed">Bikeshed!</a></h2></header>
<p>What do we call these?</p><p><a href="#classstd_1_1array__ref">std::array_ref</a>:<ul>
<li>array_slice</li><li>sub_array</li><li>pointer_range</li></ul>
</p><p>std::string_ref:<ul>
<li>sub_string</li><li>string_piece</li><li>string_view</li></ul>
</p><header><h2><a name="classstd_1_1array__ref">std::array_ref</a></h2></header>
    
<p>An <code>array_ref&lt;T&gt;</code> represents an immutable array of <code>size()</code> elements of type T. The storage for the array is *not* owned by the <code><a href="#classstd_1_1array__ref">array_ref</a></code> object, and clients must arrange for the backing store to remain live while the <code><a href="#classstd_1_1array__ref">array_ref</a></code> object is in use.</p><p>Implicit conversion operations are provided from types with contiguous iterators like <code>std::vector</code>, <code>std::string</code>, <code>std::array</code>, and primitive arrays. <code><a href="#classstd_1_1array__ref">array_ref</a></code> objects are invalidated by any operation that invalidates their underlying pointers.</p><p>One common use for <code><a href="#classstd_1_1array__ref">array_ref</a></code> is when passing arguments to a routine where you want to be able to accept a variety of array types. The usual approach here is to have the client explicitly pass in a pointer and a length, as in: <div><div class="example"><code><span class="keywordtype">void</span><span class="normal"> MyOldRoutine(</span><span class="keyword">const</span><span class="normal"> </span><span class="keywordtype">int</span><span class="normal">* elems, </span><span class="keywordtype">int</span><span class="normal"> N) {</span></code><br>
<code><span class="normal">  </span><span class="keywordflow">for</span><span class="normal"> (</span><span class="keywordtype">int</span><span class="normal"> i = 0; i &lt; N; i++) { assert(elems[i] == N - i); }</span></code><br>
<code><span class="normal">}</span></code><br>
</div></div> <p>Unfortunately, this leads to ugly and error-prone code at the call site: <div><div class="example"><code><span class="normal">std::vector&lt;int&gt; my_vector;</span></code><br><code><span class="normal"></span><span class="keywordflow">for</span><span class="normal"> (</span><span class="keywordtype">size_t</span><span class="normal"> i = 5; i &gt; 0; --i) { my_vector.push_back(i); }</span></code><br><code><span class="normal">MyOldRoutine(my_vector.data(), my_vector.size());</span></code><br><code><span class="normal"></span></code><br><code><span class="normal">std::array&lt;int, 4&gt; my_std_array = {{4, 3, 2, 1}};</span></code><br><code><span class="normal">MyOldRoutine(my_std_array.data(), my_std_array.size());</span></code><br><code><span class="normal"></span></code><br><code><span class="normal"></span><span class="keywordtype">int</span><span class="normal"> my_array[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};</span></code><br><code><span class="normal">MyOldRoutine(my_array, 10);</span></code><br><code><span class="normal"></span></code><br><code><span class="normal"></span><span class="keywordtype">int</span><span class="normal">* dyn_array = </span><span class="keyword">new</span><span class="normal"> </span><span class="keywordtype">int</span><span class="normal">[3];</span></code><br><code><span class="normal"></span><span class="keywordflow">for</span><span class="normal"> (</span><span class="keywordtype">size_t</span><span class="normal"> i = 0; i &lt; 3; ++i) { dyn_array[i] = 3 - i; }</span></code><br><code><span class="normal">MyOldRoutine(dyn_array, 3);</span></code><br></div></div> </p>
<p>Instead, you can use an <code><a href="#classstd_1_1array__ref">array_ref</a></code> as the argument to the routine: <div><div class="example"><code><span class="keywordtype">void</span><span class="normal"> MyNewRoutine(<a href="#classstd_1_1array__ref">std::array_ref&lt;int&gt;</a> a) {</span></code><br>
<code><span class="normal">  </span><span class="keywordflow">for</span><span class="normal"> (</span><span class="keywordtype">size_t</span><span class="normal"> i = 0; i &lt; a.size(); i++) { assert(a[i] == </span><span class="keywordtype">int</span><span class="normal">(a.size() - i)); }</span></code><br>
<code><span class="normal">}</span></code><br>
</div></div> </p>
<p>This makes the call sites cleaner, for the most part: <div><div class="example"><code><span class="normal">std::vector&lt;int&gt; my_vector;</span></code><br><code><span class="normal"></span><span class="keywordflow">for</span><span class="normal"> (</span><span class="keywordtype">int</span><span class="normal"> i = 5; i &gt; 0; --i) { my_vector.push_back(i); }</span></code><br><code><span class="normal">MyNewRoutine(my_vector);</span></code><br><code><span class="normal"></span></code><br><code><span class="normal">std::array&lt;int, 4&gt; my_std_array = {{4, 3, 2, 1}};</span></code><br><code><span class="normal">MyNewRoutine(my_std_array);</span></code><br><code><span class="normal"></span></code><br><code><span class="normal"></span><span class="keywordtype">int</span><span class="normal"> my_array[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};</span></code><br><code><span class="normal">MyNewRoutine(my_array);</span></code><br><code><span class="normal"></span></code><br><code><span class="normal"></span><span class="keywordtype">int</span><span class="normal">* dyn_array = </span><span class="keyword">new</span><span class="normal"> </span><span class="keywordtype">int</span><span class="normal">[3];</span></code><br><code><span class="normal"></span><span class="keywordflow">for</span><span class="normal"> (</span><span class="keywordtype">size_t</span><span class="normal"> i = 0; i &lt; 3; ++i) { dyn_array[i] = 3 - i; }</span></code><br><code><span class="normal">MyNewRoutine(<a href="#classstd_1_1array__ref">std::array_ref&lt;int&gt;</a>(dyn_array, 3));</span></code><br></div></div> </p>
<div><figure id="todo_1_todo000001"><figcaption>Todo</figcaption><p>The existing <code><a href="#classstd_1_1array__ref">array_ref</a></code> classes make the view const. It may be useful to extend that to allow modifications of the referenced array elements, and use <code>array_ref&lt;const T&gt;</code> for immutable views. </p></figure></div></p>    <h3>Class definition</h3><pre><code>namespace std {
  template&lt;typename T&gt;
  class array_ref {
    // types
    typedef T value_type;
    typedef const T * pointer;
    typedef const T &amp; reference;
    typedef const T &amp; const_reference;
    typedef <var>implementation_defined</var> const_iterator;
    typedef <a href="#classstd_1_1array__ref_1a8c4c87612be05a3f18d007054665470e">const_iterator</a> iterator;
    typedef std::reverse_iterator&lt; <a href="#classstd_1_1array__ref_1a8c4c87612be05a3f18d007054665470e">const_iterator</a> &gt; const_reverse_iterator;
    typedef const_reverse_iterator reverse_iterator;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;

    // construct/copy
    constexpr <a href="#classstd_1_1array__ref_1add61a955b623c4b7a30c86d24037a982">array_ref</a>();
    constexpr array_ref(const <a href="#classstd_1_1array__ref">array_ref</a> &amp;);
    <a href="#classstd_1_1array__ref">array_ref</a> &amp; operator=(const <a href="#classstd_1_1array__ref">array_ref</a> &amp;);
    constexpr array_ref(const T * array, size_t length);
    <a href="#classstd_1_1array__ref_1a8dba61babaedd93223e28a31567a520a">array_ref</a>(const vector&lt; T &gt; &amp; v);
    template&lt;size_t N&gt;
    constexpr array_ref(const T(&amp;a)[N]);
    template&lt;size_t N&gt;
    constexpr <a href="#classstd_1_1array__ref_1ab193257800c7bd8e5841f6e6d3916735">array_ref</a>(const std::array&lt; T, N &gt; &amp; a);
    constexpr <a href="#classstd_1_1array__ref">array_ref</a> <a href="#classstd_1_1array__ref_1a6063759cf7f130688117a7f1a3673fdd">substr</a>(size_type pos, size_type n=size_type(-1)) const;

    // iterators
    constexpr <a href="#classstd_1_1array__ref_1a8c4c87612be05a3f18d007054665470e">const_iterator</a> begin() const;
    constexpr <a href="#classstd_1_1array__ref_1a8c4c87612be05a3f18d007054665470e">const_iterator</a> end() const;
    constexpr <a href="#classstd_1_1array__ref_1a8c4c87612be05a3f18d007054665470e">const_iterator</a> cbegin() const;
    constexpr <a href="#classstd_1_1array__ref_1a8c4c87612be05a3f18d007054665470e">const_iterator</a> cend() const;
    const_reverse_iterator rbegin() const;
    const_reverse_iterator rend() const;
    const_reverse_iterator crbegin() const;
    const_reverse_iterator crend() const;

    // capacity
    constexpr size_type size() const;
    constexpr size_type max_size() const;
    constexpr bool empty() const;

    // element access
    constexpr const T &amp; operator[](size_t i) const;
    constexpr const T &amp; at(size_t i) const;
    constexpr const T &amp; front() const;
    constexpr const T &amp; back() const;
    constexpr const T * <a href="#classstd_1_1array__ref_1a8ec10be5a4bd1cf4939fd0c5f342e158">data</a>() const;

    // Outgoing conversion operators
    explicit <a href="#classstd_1_1array__ref_1a559364a82928735ce3edd8cf801558d6">operator vector&lt; T &gt;</a>() const;
    vector&lt; T &gt; vec() const;
    template&lt;typename traits, typename Allocator&gt;
    explicit <a href="#classstd_1_1array__ref_1a86eac7fefe84618086f55750d5abb914">operator basic_string&lt; T, traits, Allocator &gt;</a>() const;
    basic_string&lt; T &gt; str() const;

    // mutators
    void <a href="#classstd_1_1array__ref_1a2528f8c2c6bafd05f856914fd76bc1a0">clear</a>();
    void <a href="#classstd_1_1array__ref_1a7f801b7f7e306e9be581234192ef8cf1">remove_prefix</a>(size_type n);
    void <a href="#classstd_1_1array__ref_1a50ac0527e990678bcd85a4a2dc1fe876">remove_suffix</a>(size_type n);
    void <a href="#classstd_1_1array__ref_1ab5c9ea22610de81623850620adbfa7be">pop_back</a>();
    void <a href="#classstd_1_1array__ref_1a669f68201a6fda493607ca2e42113569">pop_front</a>();
  };

  // deducing constructor wrappers
  template&lt;typename T&gt;
  constexpr <a href="#classstd_1_1array__ref">array_ref</a>&lt; T &gt; make_array_ref(const T * array, size_t length);
  template&lt;typename T, size_t N&gt;
  constexpr <a href="#classstd_1_1array__ref">array_ref</a>&lt; T &gt; make_array_ref(const T(&amp;a)[N]);
  template&lt;typename T&gt;
  <a href="#classstd_1_1array__ref">array_ref</a>&lt; T &gt; make_array_ref(const vector&lt; T &gt; &amp; v);
}</code></pre><section><header><h3>Member semantics</h3></header><section><header><h4>deducing constructor wrappers</h4></header><p>These functions do the same thing as the constructor with the same signature. They just allow users to avoid writing the iterator type. </p></section><section><header><h4>types</h4></header><section class="function"><header><code id="classstd_1_1array__ref_1a1126098a46905514e2c2bbfe5ce30e7f">typedef const T * pointer;
</code></header>
        
<div><figure id="todo_1_todo000002"><figcaption>Todo</figcaption><p>Should the pointer type be configurable as a template argument? </p></figure></div>        </section><section class="function"><header><code id="classstd_1_1array__ref_1a8c4c87612be05a3f18d007054665470e">typedef <var>implementation_defined</var> const_iterator;
</code></header>
        
<p>   random-access, contiguous iterator type </p>        </section><section class="function"><header><code id="classstd_1_1array__ref_1aea46a5da669b2ddd46efc8fdd8571c24">typedef <a href="#classstd_1_1array__ref_1a8c4c87612be05a3f18d007054665470e">const_iterator</a> iterator;
</code></header>
        
<p>Because <a href="#classstd_1_1array__ref">array_ref</a> controls a constant sequence, iterator and const_iterator are the same type. </p>        </section></section><section><header><h4>construct/copy</h4></header><section class="function"><header><code id="classstd_1_1array__ref_1add61a955b623c4b7a30c86d24037a982">constexpr <a href="#classstd_1_1array__ref_1add61a955b623c4b7a30c86d24037a982">array_ref</a>();
</code></header>
        
<dl class="attribute"><dt>Postcondition:</dt><dd><p><code>empty() == true</code> </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1array__ref_1a8dba61babaedd93223e28a31567a520a"><a href="#classstd_1_1array__ref_1a8dba61babaedd93223e28a31567a520a">array_ref</a>(const vector&lt; T &gt; &amp; v);
</code></header>
        
<div><figure id="todo_1_todo000003"><figcaption>Todo</figcaption><p>Arguably, this conversion should be a std::vector conversion operator. </p></figure></div>        </section><section class="function"><header><code id="classstd_1_1array__ref_1ab193257800c7bd8e5841f6e6d3916735">template&lt;size_t N&gt;
constexpr <a href="#classstd_1_1array__ref_1ab193257800c7bd8e5841f6e6d3916735">array_ref</a>(const std::array&lt; T, N &gt; &amp; a);
</code></header>
        
<div><figure id="todo_1_todo000004"><figcaption>Todo</figcaption><p>Arguably, this conversion should be a std::array conversion operator. </p></figure></div>        </section><section class="function"><header><code id="classstd_1_1array__ref_1a6063759cf7f130688117a7f1a3673fdd">constexpr <a href="#classstd_1_1array__ref">array_ref</a> <a href="#classstd_1_1array__ref_1a6063759cf7f130688117a7f1a3673fdd">substr</a>(size_type pos, size_type n=size_type(-1)) const;
</code></header>
        
<div><figure id="todo_1_todo000005"><figcaption>Todo</figcaption><p>See <code><a href="#classstd_1_1basic__string__ref_1a02240d1c45387eb1c69238790a8693a5">basic_string_ref::substr</a></code> for interface questions. We want something like this on <code><a href="#classstd_1_1array__ref">array_ref</a></code>, but probably not with this name. </p></figure></div>        </section></section><section><header><h4>element access</h4></header><section class="function"><header><code id="classstd_1_1array__ref_1a8ec10be5a4bd1cf4939fd0c5f342e158">constexpr const T * <a href="#classstd_1_1array__ref_1a8ec10be5a4bd1cf4939fd0c5f342e158">data</a>() const;
</code></header>
        
<dl class="attribute"><dt>Returns:</dt><dd><p>A pointer such that [<code><a href="#classstd_1_1array__ref_1a8ec10be5a4bd1cf4939fd0c5f342e158">data()</a></code>,<code><a href="#classstd_1_1array__ref_1a8ec10be5a4bd1cf4939fd0c5f342e158">data()</a> + size()</code>) is a valid range. For a non-empty <a href="#classstd_1_1array__ref">array_ref</a>, <code><a href="#classstd_1_1array__ref_1a8ec10be5a4bd1cf4939fd0c5f342e158">data()</a> == &amp;front()</code>. </p></dd></dl>
        </section></section><section><header><h4>Outgoing conversion operators</h4></header><p>These functions provide explicit conversions to selected other contiguous sequence types using those types' iterator-range constructors. We provide both explicit conversion operators for use in variable initialization and short member functions for use in function calls.</p><p>The operators are <code>explicit</code> to avoid accidental O(N) operations on type mismatches. </p><section class="function"><header><code id="classstd_1_1array__ref_1a559364a82928735ce3edd8cf801558d6">explicit <a href="#classstd_1_1array__ref_1a559364a82928735ce3edd8cf801558d6">operator vector&lt; T &gt;</a>() const;
</code></header>
        
<div><figure id="todo_1_todo000006"><figcaption>Todo</figcaption><p>Arguably, this conversion should be a std::vector constructor. </p></figure></div>        </section><section class="function"><header><code id="classstd_1_1array__ref_1a86eac7fefe84618086f55750d5abb914">template&lt;typename traits, typename Allocator&gt;
explicit <a href="#classstd_1_1array__ref_1a86eac7fefe84618086f55750d5abb914">operator basic_string&lt; T, traits, Allocator &gt;</a>() const;
</code></header>
        
<div><figure id="todo_1_todo000007"><figcaption>Todo</figcaption><p>Arguably, this conversion should be a std::basic_string constructor. </p></figure></div>        </section></section><section><header><h4>mutators</h4></header><section class="function"><header><code id="classstd_1_1array__ref_1a2528f8c2c6bafd05f856914fd76bc1a0">void <a href="#classstd_1_1array__ref_1a2528f8c2c6bafd05f856914fd76bc1a0">clear</a>();
</code></header>
        
<dl class="attribute"><dt>Effects:</dt><dd><p>Resets *this to its default-constructed state. </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1array__ref_1a7f801b7f7e306e9be581234192ef8cf1">void <a href="#classstd_1_1array__ref_1a7f801b7f7e306e9be581234192ef8cf1">remove_prefix</a>(size_type n);
</code></header>
        
<dl class="attribute"><dt>Effects:</dt><dd><p>Advances the start pointer of this <a href="#classstd_1_1array__ref">array_ref</a> past <code>n</code> elements without moving the end pointer. </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1array__ref_1a50ac0527e990678bcd85a4a2dc1fe876">void <a href="#classstd_1_1array__ref_1a50ac0527e990678bcd85a4a2dc1fe876">remove_suffix</a>(size_type n);
</code></header>
        
<dl class="attribute"><dt>Effects:</dt><dd><p>Moves the end pointer of this <a href="#classstd_1_1array__ref">array_ref</a> earlier by <code>n</code> elements without moving the start pointer. </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1array__ref_1ab5c9ea22610de81623850620adbfa7be">void <a href="#classstd_1_1array__ref_1ab5c9ea22610de81623850620adbfa7be">pop_back</a>();
</code></header>
        
<dl class="attribute"><dt>Effects:</dt><dd><p><code>remove_suffix(1)</code> </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1array__ref_1a669f68201a6fda493607ca2e42113569">void <a href="#classstd_1_1array__ref_1a669f68201a6fda493607ca2e42113569">pop_front</a>();
</code></header>
        
<dl class="attribute"><dt>Effects:</dt><dd><p><code>remove_prefix(1)</code> </p></dd></dl>
        </section></section></section><header><h2><a name="classstd_1_1basic__string__ref">std::basic_string_ref</a></h2></header>
    
<p>A string-like object that points to a sized piece of memory, similar to an <code>array_ref&lt;charT&gt;</code>.</p><p>We provide implicit constructors so users can pass in a <code>const char*</code> or a <code>std::string</code> wherever a <code>string_ref</code> is expected.</p><p>It is expected that user-defined string-like types will define an implicit conversion to <code>string_ref</code> (or another appropriate instance of <code><a href="#classstd_1_1basic__string__ref">basic_string_ref</a></code>) to interoperate with functions that need to read strings.</p><p>Unlike <code>std::strings</code> and string literals, <code><a href="#classstd_1_1basic__string__ref_1a24526ed92faaf540c60fe12fd36fdedf">data()</a></code> may return a pointer to a buffer that is not null-terminated. Therefore it is typically a mistake to pass <code><a href="#classstd_1_1basic__string__ref_1a24526ed92faaf540c60fe12fd36fdedf">data()</a></code> to a routine that takes just a <code>const charT*</code> and expects a null-terminated string.</p><p><code>std::hash</code> specializations shall be provided for <code>string_ref</code>, <code>wstring_ref</code>, <code>u16string_ref</code>, and <code>u32string_ref</code>.</p><p>Methods on <code>basic_string_ref&lt;charT&gt;</code> with the same name as methods on <code>array_ref&lt;charT&gt;</code> are intended to have the same semantics unless the difference is noted specifically.</p><div><figure id="todo_1_todo000008"><figcaption>Todo</figcaption><p>Should <code>string_ref</code> inherit from <code><a href="#classstd_1_1array__ref">array_ref</a></code>? It seems like a straightforward extension, but there's a risk in that some of <code>basic_string_ref&lt;charT, traits&gt;</code>'s behavior depends on that <code>traits</code> parameter, which isn't propagated to the <code>array_ref&lt;charT&gt;</code> base class. If <code>traits::eq</code> isn't simply <code>operator==(charT)</code>, this would cause the behavior to depend on whether a <code><a href="#classstd_1_1basic__string__ref">basic_string_ref</a></code> has been upcasted to <code><a href="#classstd_1_1array__ref">array_ref</a></code>. For the 4 specializations of <code>char_traits&lt;&gt;</code> defined by the standard, this is guaranteed, but it's not necessarily true for user-defined types. </p></figure></div>    <h3>Class definition</h3><pre><code>namespace std {
  template&lt;typename charT, typename traits&gt;
  class basic_string_ref {
    // types
    typedef charT value_type;
    typedef const charT * pointer;
    typedef const charT &amp; reference;
    typedef const charT &amp; const_reference;
    typedef <var>implementation_defined</var> const_iterator;
    typedef <a href="#classstd_1_1basic__string__ref_1ac7b0137c489a9a8c37d3896f0dc31d18">const_iterator</a> iterator;
    typedef std::reverse_iterator&lt; <a href="#classstd_1_1basic__string__ref_1ac7b0137c489a9a8c37d3896f0dc31d18">const_iterator</a> &gt; const_reverse_iterator;
    typedef const_reverse_iterator reverse_iterator;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    static constexpr size_type npos = size_type(-1);

    // construct/copy
    constexpr <a href="#classstd_1_1basic__string__ref_1acfaf560a9a5637bfd16a0523f1026f2a">basic_string_ref</a>();
    constexpr basic_string_ref(const <a href="#classstd_1_1basic__string__ref">basic_string_ref</a> &amp;);
    <a href="#classstd_1_1basic__string__ref">basic_string_ref</a> &amp; operator=(const <a href="#classstd_1_1basic__string__ref">basic_string_ref</a> &amp;);
    <a href="#classstd_1_1basic__string__ref_1a59580edacd4ca7dafb1268e9eb47241c">basic_string_ref</a>(const charT * str);
    template&lt;typename Allocator&gt;
    <a href="#classstd_1_1basic__string__ref_1a5e4493589c4aaec98b281aed009ca3ae">basic_string_ref</a>(const basic_string&lt; charT, traits, Allocator &gt; &amp; str);
    constexpr <a href="#classstd_1_1basic__string__ref_1af4c919da56742cfc101ec69386af5d53">basic_string_ref</a>(const charT * str, size_type len);

    // iterators
    constexpr <a href="#classstd_1_1basic__string__ref_1ac7b0137c489a9a8c37d3896f0dc31d18">const_iterator</a> begin() const;
    constexpr <a href="#classstd_1_1basic__string__ref_1ac7b0137c489a9a8c37d3896f0dc31d18">const_iterator</a> end() const;
    constexpr <a href="#classstd_1_1basic__string__ref_1ac7b0137c489a9a8c37d3896f0dc31d18">const_iterator</a> cbegin() const;
    constexpr <a href="#classstd_1_1basic__string__ref_1ac7b0137c489a9a8c37d3896f0dc31d18">const_iterator</a> cend() const;
    const_reverse_iterator rbegin() const;
    const_reverse_iterator rend() const;
    const_reverse_iterator crbegin() const;
    const_reverse_iterator crend() const;

    // capacity
    constexpr size_type size() const;
    constexpr size_type max_size() const;
    constexpr bool empty() const;
    constexpr size_type <a href="#classstd_1_1basic__string__ref_1a62116368828024954811a76589772e73">length</a>() const;

    // element access
    constexpr const charT &amp; operator[](size_t i) const;
    const charT &amp; at(size_t i) const;
    constexpr const charT &amp; front() const;
    constexpr const charT &amp; back() const;
    constexpr const charT * <a href="#classstd_1_1basic__string__ref_1a24526ed92faaf540c60fe12fd36fdedf">data</a>() const;

    // Outgoing conversion operators
    constexpr <a href="#classstd_1_1basic__string__ref_1a2a1ee959b5371252428c0ab57835e138">operator array_ref&lt; const charT &gt;</a>() const;
    template&lt;typename Allocator&gt;
    explicit <a href="#classstd_1_1basic__string__ref_1ad3f7b78354a9e46f1d78cdacfa41cb5c">operator basic_string&lt; charT, traits, Allocator &gt;</a>() const;
    basic_string&lt; charT, traits &gt; <a href="#classstd_1_1basic__string__ref_1ab73b435c74cf329dea771d85b8c7de48">str</a>() const;

    // mutators
    void <a href="#classstd_1_1basic__string__ref_1a85f39a5e45d6efc3c75c21ad48307586">clear</a>();
    void <a href="#classstd_1_1basic__string__ref_1aa5c42d285bc01c32eda9ec3e83a3a098">remove_prefix</a>(size_type n);
    void <a href="#classstd_1_1basic__string__ref_1accde94ea00561b9e8c38b6df879f7bc9">remove_suffix</a>(size_type n);
    void <a href="#classstd_1_1basic__string__ref_1ab580765e1b905ace0b7494324c980f3b">pop_back</a>();
    void <a href="#classstd_1_1basic__string__ref_1a95f2a25c370d32c5fa603f69778420eb">pop_front</a>();

    // string operations with the same semantics as std::basic_string
    int compare(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a> x) const;
    constexpr <a href="#classstd_1_1basic__string__ref">basic_string_ref</a> <a href="#classstd_1_1basic__string__ref_1a02240d1c45387eb1c69238790a8693a5">substr</a>(size_type pos, size_type n=npos) const;
    size_type <a href="#classstd_1_1basic__string__ref_1ab23a4885309a116e8e67349fe0950290">copy</a>(charT * buf) const;
    size_type find(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a> s) const;
    size_type find(charT c) const;
    size_type rfind(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a> s) const;
    size_type rfind(charT c) const;
    size_type find_first_of(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a> s) const;
    size_type find_first_of(charT c) const;
    size_type find_first_not_of(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a> s) const;
    size_type find_first_not_of(charT c) const;
    size_type find_last_of(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a> s) const;
    size_type find_last_of(charT c) const;
    size_type find_last_not_of(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a> s) const;
    size_type find_last_not_of(charT c) const;

    // new string operations
    bool <a href="#classstd_1_1basic__string__ref_1a2577f6f7b9d8b1c1121d06f84033fa66">starts_with</a>(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a> x) const;
    bool <a href="#classstd_1_1basic__string__ref_1a726218a6f6faf10bad00bb9882d61a03">ends_with</a>(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a> x) const;
  };

  // Common specializations:
  typedef <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; char &gt; string_ref;
  typedef <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; char16_t &gt; u16string_ref;
  typedef <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; char32_t &gt; u32string_ref;
  typedef <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; wchar_t &gt; wstring_ref;

  // Comparison operators
  template&lt;typename charT, typename traits&gt;
  bool <a href="#classstd_1_1basic__string__ref_1a0c9d1de20d5f051a9ccc19df97a20463">operator==</a>(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; x, <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; y);
  template&lt;typename charT, typename traits&gt;
  bool operator!=(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; x, <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; y);
  template&lt;typename charT, typename traits&gt;
  bool operator&lt;(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; x, <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; y);
  template&lt;typename charT, typename traits&gt;
  bool operator&gt;(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; x, <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; y);
  template&lt;typename charT, typename traits&gt;
  bool operator&lt;=(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; x, <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; y);
  template&lt;typename charT, typename traits&gt;
  bool operator&gt;=(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; x, <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; y);

  // numeric conversions
  int stoi(const <a href="#classstd_1_1basic__string__ref">string_ref</a> &amp; str, size_t * idx=0, int base=10);
  long stol(const <a href="#classstd_1_1basic__string__ref">string_ref</a> &amp; str, size_t * idx=0, int base=10);
  unsigned long stoul(const <a href="#classstd_1_1basic__string__ref">string_ref</a> &amp; str, size_t * idx=0, int base=10);
  long long stoll(const <a href="#classstd_1_1basic__string__ref">string_ref</a> &amp; str, size_t * idx=0, int base=10);
  unsigned long long stoull(const <a href="#classstd_1_1basic__string__ref">string_ref</a> &amp; str, size_t * idx=0, int base=10);
  float stof(const <a href="#classstd_1_1basic__string__ref">string_ref</a> &amp; str, size_t * idx=0);
  double stod(const <a href="#classstd_1_1basic__string__ref">string_ref</a> &amp; str, size_t * idx=0);
  long double stold(const <a href="#classstd_1_1basic__string__ref">string_ref</a> &amp; str, size_t * idx=0);
  int stoi(const <a href="#classstd_1_1basic__string__ref">wstring_ref</a> &amp; str, size_t * idx=0, int base=10);
  long stol(const <a href="#classstd_1_1basic__string__ref">wstring_ref</a> &amp; str, size_t * idx=0, int base=10);
  unsigned long stoul(const <a href="#classstd_1_1basic__string__ref">wstring_ref</a> &amp; str, size_t * idx=0, int base=10);
  long long stoll(const <a href="#classstd_1_1basic__string__ref">wstring_ref</a> &amp; str, size_t * idx=0, int base=10);
  unsigned long long stoull(const <a href="#classstd_1_1basic__string__ref">wstring_ref</a> &amp; str, size_t * idx=0, int base=10);
  float stof(const <a href="#classstd_1_1basic__string__ref">wstring_ref</a> &amp; str, size_t * idx=0);
  double stod(const <a href="#classstd_1_1basic__string__ref">wstring_ref</a> &amp; str, size_t * idx=0);
  long double stold(const <a href="#classstd_1_1basic__string__ref">wstring_ref</a> &amp; str, size_t * idx=0);
}</code></pre><section><header><h3>Member semantics</h3></header><section><header><h4>Comparison operators</h4></header><section class="function"><header><code id="classstd_1_1basic__string__ref_1a0c9d1de20d5f051a9ccc19df97a20463">template&lt;typename charT, typename traits&gt;
bool <a href="#classstd_1_1basic__string__ref_1a0c9d1de20d5f051a9ccc19df97a20463">operator==</a>(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; x, <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>&lt; charT, traits &gt; y);
</code></header>
<p>Note that equality can be implemented faster than comparison. </p>        
        </section></section><section><header><h4>numeric conversions</h4></header><p>Each function <code>sto<em>x</em></code> in this section behaves as if it calls <pre><code>sto<em>x</em>(str.str(), idx, base)</code></pre> Ideally with less copying.</p><div><figure id="todo_1_todo000009"><figcaption>Todo</figcaption><p>Instead of passing the idx parameter, we could define <code>sto<em>x</em>_consume(str, base)</code> as <br>
 <code>size_t idx; <br>
 auto result = sto<em>x</em>(str.str(), &amp;idx, base); <br>
 str.remove_prefix(idx); <br>
 return result;</code></p></figure></div></section><section><header><h4>types</h4></header><section class="function"><header><code id="classstd_1_1basic__string__ref_1ac7b0137c489a9a8c37d3896f0dc31d18">typedef <var>implementation_defined</var> const_iterator;
</code></header>
        
<p>   random-access, contiguous iterator type </p>        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1a797a5c091c22a35972ebdcfebe5432f3">typedef <a href="#classstd_1_1basic__string__ref_1ac7b0137c489a9a8c37d3896f0dc31d18">const_iterator</a> iterator;
</code></header>
        
<p>Because <code>string_ref</code> controls a constant sequence, <code>iterator</code> and <code>const_iterator</code> are the same type. </p>        </section></section><section><header><h4>construct/copy</h4></header><p><code>std::string's</code> substring constructor is omitted because <code>string_ref(str).substr(pos, n)</code> is clearer </p><section class="function"><header><code id="classstd_1_1basic__string__ref_1acfaf560a9a5637bfd16a0523f1026f2a">constexpr <a href="#classstd_1_1basic__string__ref_1acfaf560a9a5637bfd16a0523f1026f2a">basic_string_ref</a>();
</code></header>
        
<dl class="attribute"><dt>Postcondition:</dt><dd><p><code>empty() == true</code> </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1a59580edacd4ca7dafb1268e9eb47241c"><a href="#classstd_1_1basic__string__ref_1a59580edacd4ca7dafb1268e9eb47241c">basic_string_ref</a>(const charT * str);
</code></header>
        
<dl class="attribute"><dt>Postcondition:</dt><dd><p><code><a href="#classstd_1_1basic__string__ref_1a24526ed92faaf540c60fe12fd36fdedf">data()</a> == str</code>, and <code>size()</code> is <code>0</code> if <code>str == nullptr</code> or <code>strlen(str)</code> otherwise. </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1a5e4493589c4aaec98b281aed009ca3ae">template&lt;typename Allocator&gt;
<a href="#classstd_1_1basic__string__ref_1a5e4493589c4aaec98b281aed009ca3ae">basic_string_ref</a>(const basic_string&lt; charT, traits, Allocator &gt; &amp; str);
</code></header>
        
<p><dl class="attribute"><dt>Postcondition:</dt><dd><p><code><a href="#classstd_1_1basic__string__ref_1a24526ed92faaf540c60fe12fd36fdedf">data()</a> == str.data() &amp;&amp; size() == str.size()</code></p></dd></dl>
<div><figure id="todo_1_todo000010"><figcaption>Todo</figcaption><p>Arguably, this conversion should be a std::basic_string conversion operator. </p></figure></div></p>        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1af4c919da56742cfc101ec69386af5d53">constexpr <a href="#classstd_1_1basic__string__ref_1af4c919da56742cfc101ec69386af5d53">basic_string_ref</a>(const charT * str, size_type len);
</code></header>
        
<dl class="attribute"><dt>Postcondition:</dt><dd><p><code><a href="#classstd_1_1basic__string__ref_1a24526ed92faaf540c60fe12fd36fdedf">data()</a> == str &amp;&amp; size() == len</code> </p></dd></dl>
        </section></section><section><header><h4>capacity</h4></header><section class="function"><header><code id="classstd_1_1basic__string__ref_1a62116368828024954811a76589772e73">constexpr size_type <a href="#classstd_1_1basic__string__ref_1a62116368828024954811a76589772e73">length</a>() const;
</code></header>
<p>Alias for <code>size()</code> for string compatibility. </p>        
        </section></section><section><header><h4>element access</h4></header><section class="function"><header><code id="classstd_1_1basic__string__ref_1a24526ed92faaf540c60fe12fd36fdedf">constexpr const charT * <a href="#classstd_1_1basic__string__ref_1a24526ed92faaf540c60fe12fd36fdedf">data</a>() const;
</code></header>
        
<dl class="attribute"><dt>Returns:</dt><dd><p>A pointer such that [<code><a href="#classstd_1_1basic__string__ref_1a24526ed92faaf540c60fe12fd36fdedf">data()</a></code>,<code><a href="#classstd_1_1basic__string__ref_1a24526ed92faaf540c60fe12fd36fdedf">data()</a> + size()</code>) is a valid range. For a non-empty <a href="#classstd_1_1basic__string__ref">basic_string_ref</a>, <code><a href="#classstd_1_1basic__string__ref_1a24526ed92faaf540c60fe12fd36fdedf">data()</a> == &amp;front()</code>. </p></dd></dl>
        </section></section><section><header><h4>Outgoing conversion operators</h4></header><section class="function"><header><code id="classstd_1_1basic__string__ref_1a2a1ee959b5371252428c0ab57835e138">constexpr <a href="#classstd_1_1basic__string__ref_1a2a1ee959b5371252428c0ab57835e138">operator array_ref&lt; const charT &gt;</a>() const;
</code></header>
        
<dl class="attribute"><dt>Returns:</dt><dd><p>An <code><a href="#classstd_1_1array__ref">array_ref</a></code> for this <code>basic_string_ref's</code> sequence of characters. </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1ad3f7b78354a9e46f1d78cdacfa41cb5c">template&lt;typename Allocator&gt;
explicit <a href="#classstd_1_1basic__string__ref_1ad3f7b78354a9e46f1d78cdacfa41cb5c">operator basic_string&lt; charT, traits, Allocator &gt;</a>() const;
</code></header>
        
<p><dl class="attribute"><dt>Returns:</dt><dd><p>A new <code>string</code> containing the sequence referenced by <code>*this</code>.</p></dd></dl>
The operator is <code>explicit</code> to avoid accidental O(N) operations on type mismatches.</p><p>Unlike <code><a href="#classstd_1_1array__ref">array_ref</a></code>, this operator preserves the <code>traits</code> type.</p><div><figure id="todo_1_todo000011"><figcaption>Todo</figcaption><p>Arguably, this conversion should be a std::basic_string constructor. </p></figure></div>        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1ab73b435c74cf329dea771d85b8c7de48">basic_string&lt; charT, traits &gt; <a href="#classstd_1_1basic__string__ref_1ab73b435c74cf329dea771d85b8c7de48">str</a>() const;
</code></header>
        
<p><dl class="attribute"><dt>Returns:</dt><dd><p><code>basic_string&lt;charT, traits&gt;(*this);</code></p></dd></dl>
Unlike <code><a href="#classstd_1_1array__ref">array_ref</a></code>, this function preserves the <code>traits</code> type. </p>        </section></section><section><header><h4>mutators</h4></header><section class="function"><header><code id="classstd_1_1basic__string__ref_1a85f39a5e45d6efc3c75c21ad48307586">void <a href="#classstd_1_1basic__string__ref_1a85f39a5e45d6efc3c75c21ad48307586">clear</a>();
</code></header>
        
<dl class="attribute"><dt>Effects:</dt><dd><p>Resets *this to its default-constructed state. </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1aa5c42d285bc01c32eda9ec3e83a3a098">void <a href="#classstd_1_1basic__string__ref_1aa5c42d285bc01c32eda9ec3e83a3a098">remove_prefix</a>(size_type n);
</code></header>
        
<dl class="attribute"><dt>Effects:</dt><dd><p>Advances the start pointer of this <a href="#classstd_1_1basic__string__ref">basic_string_ref</a> past <code>n</code> elements without moving the end pointer. </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1accde94ea00561b9e8c38b6df879f7bc9">void <a href="#classstd_1_1basic__string__ref_1accde94ea00561b9e8c38b6df879f7bc9">remove_suffix</a>(size_type n);
</code></header>
        
<dl class="attribute"><dt>Effects:</dt><dd><p>Moves the end pointer of this <a href="#classstd_1_1basic__string__ref">basic_string_ref</a> earlier by <code>n</code> elements without moving the start pointer. </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1ab580765e1b905ace0b7494324c980f3b">void <a href="#classstd_1_1basic__string__ref_1ab580765e1b905ace0b7494324c980f3b">pop_back</a>();
</code></header>
        
<dl class="attribute"><dt>Effects:</dt><dd><p><code>remove_suffix(1)</code> </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1a95f2a25c370d32c5fa603f69778420eb">void <a href="#classstd_1_1basic__string__ref_1a95f2a25c370d32c5fa603f69778420eb">pop_front</a>();
</code></header>
        
<dl class="attribute"><dt>Effects:</dt><dd><p><code>remove_prefix(1)</code> </p></dd></dl>
        </section></section><section><header><h4>string operations with the same semantics as std::basic_string</h4></header><p>Unlike std::string, string_ref provides no whole-string methods with <code>position</code> or <code>length</code> parameters. Instead, use the <code><a href="#classstd_1_1basic__string__ref_1a02240d1c45387eb1c69238790a8693a5">substr()</a></code> method to create the character sequence you're actually interested in, and use that. </p><section class="function"><header><code id="classstd_1_1basic__string__ref_1a02240d1c45387eb1c69238790a8693a5">constexpr <a href="#classstd_1_1basic__string__ref">basic_string_ref</a> <a href="#classstd_1_1basic__string__ref_1a02240d1c45387eb1c69238790a8693a5">substr</a>(size_type pos, size_type n=npos) const;
</code></header>
        
<div><figure id="todo_1_todo000012"><figcaption>Todo</figcaption><p>It would be nice to have a function that accepts negative arguments and interprets them like <a href="http://docs.python.org/py3k/library/stdtypes.html#sequence-types-str-bytes-bytearray-list-tuple-range">Python</a>, <a href="http://www.ruby-doc.org/core-1.9.3/String.html#method-i-5B-5D">Ruby</a>, and <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/slice">JavaScript</a>? However, <code><a href="#classstd_1_1basic__string__ref_1a02240d1c45387eb1c69238790a8693a5">substr()</a></code> takes a start and a <em>length</em>, not a start and an <em>end</em>, which prevents this from being a simple extension. Should we add <code>slice()</code> and deprecate <code><a href="#classstd_1_1basic__string__ref_1a02240d1c45387eb1c69238790a8693a5">substr()</a></code>? </p></figure></div>        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1ab23a4885309a116e8e67349fe0950290">size_type <a href="#classstd_1_1basic__string__ref_1ab23a4885309a116e8e67349fe0950290">copy</a>(charT * buf) const;
</code></header>
        
<p>Copy is more likely than the other methods to be used with an <code><em>n</em></code> parameter since it can be the valid length of the character buffer. Still <code>this-&gt;copy(buf, n)</code> can be replaced with <code>this-&gt;substr(0, n).copy(buf)</code>, so I've removed the <code>n</code> from here too.</p>        </section></section><section><header><h4>new string operations</h4></header><section class="function"><header><code id="classstd_1_1basic__string__ref_1a2577f6f7b9d8b1c1121d06f84033fa66">bool <a href="#classstd_1_1basic__string__ref_1a2577f6f7b9d8b1c1121d06f84033fa66">starts_with</a>(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a> x) const;
</code></header>
        
<dl class="attribute"><dt>Returns:</dt><dd><p><code>true</code> if <code>x</code> is a prefix of <code>*this</code>. </p></dd></dl>
        </section><section class="function"><header><code id="classstd_1_1basic__string__ref_1a726218a6f6faf10bad00bb9882d61a03">bool <a href="#classstd_1_1basic__string__ref_1a726218a6f6faf10bad00bb9882d61a03">ends_with</a>(<a href="#classstd_1_1basic__string__ref">basic_string_ref</a> x) const;
</code></header>
        
<dl class="attribute"><dt>Returns:</dt><dd><p><code>true</code> if <code>x</code> is a suffix of <code>*this</code>. </p></dd></dl>
        </section></section></section>
</section>
<section>
<header><h2><a name="index_1misc">Miscellaneous other changes</a></h2></header>
<p>Certain other pieces of the library should change to make life easier for <code>array_ref&lt;&gt;</code> and <code>string_ref</code>.</p><ul>
<li>Several of the <code>char_traits</code> methods could be <code>constexpr</code>.</li><li>It would be helpful to be able to provide separate definitions for the <code>constexpr</code> and non-<code>constexpr</code> versions of a function. Specifically, sometimes the fastest-executing implementation isn't in a form that <code>constexpr</code> accepts, but there's still a possible <code>constexpr</code> implementation.</li></ul>
</section>
<section>
<header><h2><a name="index_1future">Future work</a></h2></header>
<ul>
<li>
<p>It might make sense for <code>std::array_ref&lt;T&gt;</code> to inherit from <code>std::range&lt;T*&gt;</code> when/if that gets standardized. On the other hand: <ol>
<li>
<code>range&lt;T*&gt;</code> will have an implicit conversion operator from anything with <code>begin()</code> and <code>end()</code> methods, so it'll already implicitly convert from <code>array_ref&lt;T&gt;</code>. Will the inheritance still help with code like the following? <pre><code>template&lt;typename T&gt; void foo(std::range&lt;T&gt;)</code></pre>  </li>
<li>
<code>range&lt;T*&gt;</code> may obviate the need for <code>array_ref&lt;T&gt;</code>. One difficulty with using <code>range&lt;T*&gt;</code> instead of <code>array_ref&lt;T&gt;</code> is that <code>range&lt;Iterator&gt;</code> will probably be implicitly constructible from anything with a begin/end, but non-template functions may want to take <code>range&lt;T*&gt;</code> instead. One way to deal with this would be for <code>range&lt;T*&gt;</code> to be specialized, adding constructors from arbitrary contiguous iterators, but that could introduce ambiguities with functions taking <code>range&lt;TplArg&gt;</code>. </li>
</ol>
</p></li>
<li>
<p><code>std::sub_match</code> ([re.submatch]) should probably inherit from <code>std::string_ref</code>, but the fact that it takes any bidirectional iterator makes that tricky.</p></li>
<li>
<p>Consider replacing these conversion operators with new constructor overloads on the target types.</p></li>
<li>
<p>Consider adding <code>starts_with</code> and <code>ends_with</code> methods to <code>basic_string</code>.</p></li>
</ul>
<header><h2>Open questions</h2></header>
<dl><dt><a id="todo_1_todo000009"></a>Group numeric conversions  </dt><dd>Instead of passing the idx parameter, we could define <code>sto<em>x</em>_consume(str, base)</code> as <br>
 <code>size_t idx; <br>
 auto result = sto<em>x</em>(str.str(), &amp;idx, base); <br>
 str.remove_prefix(idx); <br>
 return result;</code> </dd><dt><a id="todo_1_todo000001"></a>Class <a href="#classstd_1_1array__ref">std::array_ref&lt; T &gt;</a>  </dt><dd>The existing <code>array_ref</code> classes make the view const. It may be useful to extend that to allow modifications of the referenced array elements, and use <code>array_ref&lt;const T&gt;</code> for immutable views.  </dd><dt><a id="todo_1_todo000004"></a>Member <a href="#classstd_1_1array__ref_1ab193257800c7bd8e5841f6e6d3916735">std::array_ref&lt; T &gt;::array_ref</a>  (const std::array&lt; T, N &gt; &amp;a)</dt><dd>Arguably, this conversion should be a std::array conversion operator.  </dd><dt><a id="todo_1_todo000003"></a>Member <a href="#classstd_1_1array__ref_1a8dba61babaedd93223e28a31567a520a">std::array_ref&lt; T &gt;::array_ref</a>  (const vector&lt; T &gt; &amp;v)</dt><dd>Arguably, this conversion should be a std::vector conversion operator.  </dd><dt><a id="todo_1_todo000007"></a>Member <a href="#classstd_1_1array__ref_1a86eac7fefe84618086f55750d5abb914">std::array_ref&lt; T &gt;::operator basic_string&lt; T, traits, Allocator &gt;</a>  () const </dt><dd>Arguably, this conversion should be a std::basic_string constructor.  </dd><dt><a id="todo_1_todo000006"></a>Member <a href="#classstd_1_1array__ref_1a559364a82928735ce3edd8cf801558d6">std::array_ref&lt; T &gt;::operator vector&lt; T &gt;</a>  () const </dt><dd>Arguably, this conversion should be a std::vector constructor.  </dd><dt><a id="todo_1_todo000002"></a>Member <a href="#classstd_1_1array__ref_1a1126098a46905514e2c2bbfe5ce30e7f">std::array_ref&lt; T &gt;::pointer</a>  </dt><dd>Should the pointer type be configurable as a template argument?  </dd><dt><a id="todo_1_todo000005"></a>Member <a href="#classstd_1_1array__ref_1a6063759cf7f130688117a7f1a3673fdd">std::array_ref&lt; T &gt;::substr</a>  (size_type pos, size_type n=size_type(-1)) const </dt><dd>See <code>basic_string_ref::substr</code> for interface questions. We want something like this on <code>array_ref</code>, but probably not with this name.  </dd><dt><a id="todo_1_todo000008"></a>Class <a href="#classstd_1_1basic__string__ref">std::basic_string_ref&lt; charT, traits &gt;</a>  </dt><dd>Should <code>string_ref</code> inherit from <code>array_ref</code>? It seems like a straightforward extension, but there's a risk in that some of <code>basic_string_ref&lt;charT, traits&gt;</code>'s behavior depends on that <code>traits</code> parameter, which isn't propagated to the <code>array_ref&lt;charT&gt;</code> base class. If <code>traits::eq</code> isn't simply <code>operator==(charT)</code>, this would cause the behavior to depend on whether a <code>basic_string_ref</code> has been upcasted to <code>array_ref</code>. For the 4 specializations of <code>char_traits&lt;&gt;</code> defined by the standard, this is guaranteed, but it's not necessarily true for user-defined types.  </dd><dt><a id="todo_1_todo000010"></a>Member <a href="#classstd_1_1basic__string__ref_1a5e4493589c4aaec98b281aed009ca3ae">std::basic_string_ref&lt; charT, traits &gt;::basic_string_ref</a>  (const basic_string&lt; charT, traits, Allocator &gt; &amp;str)</dt><dd>Arguably, this conversion should be a std::basic_string conversion operator.  </dd><dt><a id="todo_1_todo000011"></a>Member <a href="#classstd_1_1basic__string__ref_1ad3f7b78354a9e46f1d78cdacfa41cb5c">std::basic_string_ref&lt; charT, traits &gt;::operator basic_string&lt; charT, traits, Allocator &gt;</a>  () const </dt><dd>Arguably, this conversion should be a std::basic_string constructor.  </dd><dt><a id="todo_1_todo000012"></a>Member <a href="#classstd_1_1basic__string__ref_1a02240d1c45387eb1c69238790a8693a5">std::basic_string_ref&lt; charT, traits &gt;::substr</a>  (size_type pos, size_type n=npos) const </dt><dd>It would be nice to have a function that accepts negative arguments and interprets them like <a href="http://docs.python.org/py3k/library/stdtypes.html#sequence-types-str-bytes-bytearray-list-tuple-range">Python</a>, <a href="http://www.ruby-doc.org/core-1.9.3/String.html#method-i-5B-5D">Ruby</a>, and <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/slice">JavaScript</a>? However, <code>substr()</code> takes a start and a <em>length</em>, not a start and an <em>end</em>, which prevents this from being a simple extension. Should we add <code>slice()</code> and deprecate <code>substr()</code>? </dd></dl>
    
</section>
    </body></html>