<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta content="text/html;charset=US-ASCII" http-equiv="Content-Type"/>
    <meta charset="US-ASCII"/>
    <title>string_ref: a non-owning reference to a string</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; white-space: inherit}
code {white-space: nowrap}
code wbr {white-space: normal}

.wording { max-width: 90ex; }
.wording .sectnum { margin-right: 1em; }
.wording .sectname { display: block; float: right;  }

section.numbered { counter-reset: par-num; }
.wording p:before, .wording dt:before {
    content: counter(par-num) " "; counter-increment: par-num;
    font-size: 80%; position: absolute; left: 2em}

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

.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 }
h5, h6 { font-size: 1em; }
p {margin-top: .5em; margin-bottom: .5em}
p:first-child, ul, ol {margin-top: 0}
.todo dt:not(:first-child) {margin-top: .5em}
p, li, dd {max-width: 80ex}

table { border: double; margin: 1em; }
td { text-align: center; }

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">//<![CDATA[
$(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 cur.id;
            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>ISO/IEC JTC1 SC22 WG21 N3442=12-0132</p>
      <p>Date: <time pubdate="">2012-09-23</time></p>
      <address>
        <p>Jeffrey Yasskin &lt;<a href="mailto:jyasskin@google.com">jyasskin@google.com</a>&gt;</p>
      </address>
    </div>
    <h1><code>string_ref</code>: a non-owning reference to a string</h1>
  </header>
  <nav id="toc"></nav>

  <section>
    <header><h2 id="overview">Overview</h2></header>
    <p>References to 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:</p>
    <ol>
    <li>The callee takes std::string and insists that callers copy the
    data if it was originally owned by another type.</li>

    <li>The callee takes two parameters&#8212;a <code>char*</code> and
    a length (or just <code>char*</code> and assumes
    0-termination)&#8212;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>Google and LLVM have independently implemented a string-reference type to
    encapsulate this kind of argument. <a
    href="#strings.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 <code>const</code> 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="#strings.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>Operations on <code>string_ref</code> apply to the characters in the
    string, and not the pointers that refer to the characters.  This introduces
    the possibility that the underlying characters might change while a
    <code>string_ref</code> referring to them is in an associative container,
    which would break the container, but we believe this risk is worthwhile
    because it matches existing practice and matches user intentions more
    often.</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:</p>
    <ul>
      <li><a href="#strings.string_ref.starts_with">starts_with</a></li>
      <li><a href="#strings.string_ref.ends_with">ends_with</a></li>
      <li><a href="#strings.string_ref.remove_prefix">remove_prefix</a></li>
      <li><a href="#strings.string_ref.remove_suffix">remove_suffix</a></li>
      <li>split</li>
      <li>trim</li>
      <li>consume_prefix</li>
      <li>count</li>
    </ul>

    <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:</p>
    <ul>
      <li><a href="#strings.string_ref.hash">hash</a>, as requested by c++std-lib-31935</li>
      <li><a href="#strings.conversions.numeric">numeric conversions</a></li>
    </ul>
  </section>

  <section>
    <header><h2 id="inventions">Inventions in this paper</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>. Since this
    paper builds on top of C++11, we provide an <a
    href="#strings.string_ref.operator.basic_string"><em><code>explicit</code></em>
    conversion operator</a>.</p>

    <p>Google's and LLVM's <code>string_ref</code> types provide a subset of
    <code>std::string</code>'s searching operations, but they do provide
    <code>pos</code> arguments to specify where to start the search. Because <a
    href="#strings.string_ref.substr"><code>string_ref::substr</code></a> 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 id="bikeshed">Bikeshed!</h2></header>
    <p>What do we call this class?</p>

    <ul>
      <li>string_piece</li>
      <li>string_range</li>
      <li>string_view</li>
      <li>sub_string</li>
    </ul>
  </section>

  <section>
    <header><h2 id="modifications">Modifications vs std::string</h2></header>

    <p>The interface of <code>string_ref</code> is similar to, but not exactly
    the same as the interface of <code>std::string</code>.  In general, we want
    to minimize differences between <code>std::string</code> and
    <code>string_ref</code> so that users can go back and forth between the two
    often.  This section justifies the differences whose utility we think
    overcomes that general rule.</p>

    <h3 id="additions">Additions</h3>
    <p>We should consider adding these methods to <code>std::string</code> in
    C++17, but we can't modify <code>std::string</code> in a TS, so this paper
    doesn't propose such changes.</p>
    <ul>
      <li><code><a
      href="#strings.string_ref.remove_prefix">remove_prefix()</a></code> and
      <code><a
      href="#strings.string_ref.remove_suffix">remove_suffix()</a></code> make
      it easy to parse strings using <code>string_ref</code>.  They could both
      be implemented as non-member functions (e.g. <code>str.remove_prefix(n)
      <wbr/>===<wbr/> str = str.substr(n)</code>), but it seems useful to
      provide the simplest mutators as member functions.  Note that other
      traversal primitives need to be non-members so that they're
      extensible, which may argue for pulling these out too.</li>

      <li><a href="#strings.string_ref.starts_with">starts_with</a> and <a
      href="#strings.string_ref.ends_with">ends_with</a> are common queries on
      strings.  The non-member equivalents produce calls that are somewhat
      ambiguous between <code>starts_with(haystack, needle)</code> vs
      <code>starts_with(needle, haystack)</code>, while
      <code>haystack.starts_with(needle)</code> is the only English reading of
      the member version.</li>
    </ul>

    <h3 id="removals">Removals</h3>
    <ul>
      <li><code>copy</code>: <code>std::string::copy</code> is copy
      <em>out</em>, not in.  It's not well named.  Users can always use
      <code>std::copy</code> instead.</li>

      <li><code>pos</code> and <code>n</code> parameters to methods have been
      removed from <code>string_ref</code>.  <code>std::string</code> needs
      these parameters because <code>std::string::substring</code> is an
      expensive (copying and sometimes allocating) operation.  However, these
      are always integral parameters, so the compiler can't check that their
      order is correct, and readers often have a hard time.  Because <code><a
      href="#strings.string_ref.substr">string_ref::substr</a></code> is cheap,
      we insist users call it instead of passing its arguments to other
      functions.</li>
    </ul>
  </section>

  <hr/>

  <section class="wording">
    <header><h2 id="wording">Wording</h2></header>

    <section class="numbered">
      <header><h3 id="strings.string_ref.header"><span
      class="sectnum">?.1</span> Header &lt;string_ref> synopsis <span
      class="sectname">[strings.string_ref.header]</span></h3></header>

      <pre><code>namespace std {
namespace beta {
  template&lt;typename charT, typename traits&gt; class <a href="#strings.string_ref">basic_string_ref</a>;
  typedef basic_string_ref&lt;char&gt; string_ref;
  typedef basic_string_ref&lt;char16_t&gt; u16string_ref;
  typedef basic_string_ref&lt;char32_t&gt; u32string_ref;
  typedef basic_string_ref&lt;wchar_t&gt; wstring_ref;

  // <a href="#strings.conversions.numeric">numeric conversions</a>
  int stoi(const string_ref&amp; str, size_t* idx=0, int base=10);
  long stol(const string_ref&amp; str, size_t* idx=0, int base=10);
  unsigned long stoul(const string_ref&amp; str, size_t* idx=0, int base=10);
  long long stoll(const string_ref&amp; str, size_t* idx=0, int base=10);
  unsigned long long stoull(const string_ref&amp; str, size_t* idx=0, int base=10);
  float stof(const string_ref&amp; str, size_t* idx=0);
  double stod(const string_ref&amp; str, size_t* idx=0);
  long double stold(const string_ref&amp; str, size_t* idx=0);

  int stoi(const wstring_ref&amp; str, size_t* idx=0, int base=10);
  long stol(const wstring_ref&amp; str, size_t* idx=0, int base=10);
  unsigned long stoul(const wstring_ref&amp; str, size_t* idx=0, int base=10);
  long long stoll(const wstring_ref&amp; str, size_t* idx=0, int base=10);
  unsigned long long stoull(const wstring_ref&amp; str, size_t* idx=0, int base=10);
  float stof(const wstring_ref&amp; str, size_t* idx=0);
  double stod(const wstring_ref&amp; str, size_t* idx=0);
  long double stold(const wstring_ref&amp; str, size_t* idx=0);
}
}</code></pre>
    </section>

    <section class="numbered">
      <header><h3 id="strings.string_ref"><span class="sectnum">?.2</span>
      Class template basic_string_ref <span
      class="sectname">[strings.string_ref]</span></h3></header>

      <p>A string-like object that refers to a <code>const</code> sized piece of
      memory owned by another object.</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="#strings.string_ref">basic_string_ref</a></code>)
      to interoperate with functions that need to read strings.</p>

      <p>Unlike <code>std::string</code>s and string literals, <code><a
      href="#strings.string_ref.data">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="#strings.string_ref.data">data()</a></code>
      to a routine that takes just a <code>const charT*</code> and expects a
      null-terminated string.</p>

      <pre><code>namespace std {
namespace beta {
  template&lt;typename charT, typename traits&gt;
  class basic_string_ref {
    public:
    // 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> <a href="#strings.string_ref.const_iterator">const_iterator</a>;
    typedef const_iterator iterator;
    typedef std::reverse_iterator&lt;<a href="#strings.string_ref.const_iterator">const_iterator</a>&gt; const_reverse_iterator;
    typedef const_reverse_iterator reverse_iterator;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    <span id="strings.string_ref.npos">static constexpr size_type <a href="#strings.string_ref.npos">npos</a> = size_type(-1);</span>

    // <a href="#strings.string_ref.cons">construct/copy</a>
    constexpr <a href="#strings.string_ref.cons()">basic_string_ref</a>();
    constexpr <a href="#strings.string_ref.cons(string_ref)">basic_string_ref</a>(const basic_string_ref&amp;);
    basic_string_ref&amp; <a href="#strings.string_ref.assign">operator=</a>(const basic_string_ref&amp;);
    <a href="#strings.string_ref.cons(charT*)">basic_string_ref</a>(const charT* str);
    template&lt;typename Allocator&gt;
    <a href="#strings.string_ref.cons(string)">basic_string_ref</a>(const basic_string&lt;charT, traits, Allocator&gt;&amp; str);
    constexpr <a href="#strings.string_ref.cons(charT*,len)">basic_string_ref</a>(const charT* str, size_type len);
    <a href="#strings.string_ref.cons(init_list)">basic_string_ref</a>(initializer_list&lt;charT> il);
    template&lt;typename Allocator&gt;
    explicit <a href="#strings.string_ref.operator.basic_string">operator basic_string&lt;charT, traits, Allocator&gt;</a>() const;


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

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

    // <a href="#strings.string_ref.access">element access</a>
    constexpr const charT&amp; <a href="#strings.string_ref.operator.index">operator[]</a>(size_type pos) const;
    const charT&amp; <a href="#strings.string_ref.at">at</a>(size_t pos) const;
    constexpr const charT&amp; <a href="#strings.string_ref.front">front</a>() const;
    constexpr const charT&amp; <a href="#strings.string_ref.back">back</a>() const;
    constexpr const charT* <a href="#strings.string_ref.data">data</a>() const;

    // <a href="#strings.string_ref.modifiers">modifiers</a>
    void <a href="#strings.string_ref.clear">clear</a>();
    void <a href="#strings.string_ref.remove_prefix">remove_prefix</a>(size_type n);
    void <a href="#strings.string_ref.remove_suffix">remove_suffix</a>(size_type n);

    // <a href="#strings.string_ref.ops">basic_string_ref string operations</a>
    constexpr basic_string_ref <a href="#strings.string_ref.substr">substr</a>(size_type pos, size_type n=npos) const;
    int <a href="#strings.string_ref.compare">compare</a>(basic_string_ref x) const;
    bool <a href="#strings.string_ref.starts_with">starts_with</a>(basic_string_ref x) const;
    bool <a href="#strings.string_ref.ends_with">ends_with</a>(basic_string_ref x) const;

    size_type <a href="#strings.string_ref.find">find</a>(basic_string_ref s) const;
    size_type <a href="#strings.string_ref.find">find</a>(charT c) const;
    size_type <a href="#strings.string_ref.rfind">rfind</a>(basic_string_ref s) const;
    size_type <a href="#strings.string_ref.rfind">rfind</a>(charT c) const;
    size_type <a href="#strings.string_ref.find_first_of">find_first_of</a>(basic_string_ref s) const;
    size_type <a href="#strings.string_ref.find_first_of">find_first_of</a>(charT c) const;
    size_type <a href="#strings.string_ref.find_last_of">find_last_of</a>(basic_string_ref s) const;
    size_type <a href="#strings.string_ref.find_last_of">find_last_of</a>(charT c) const;
    size_type <a href="#strings.string_ref.find_first_not_of">find_first_not_of</a>(basic_string_ref s) const;
    size_type <a href="#strings.string_ref.find_first_not_of">find_first_not_of</a>(charT c) const;
    size_type <a href="#strings.string_ref.find_last_not_of">find_last_not_of</a>(basic_string_ref s) const;
    size_type <a href="#strings.string_ref.find_last_not_of">find_last_not_of</a>(charT c) const;
  };

  // <a href="#strings.string_ref.nonmem.compare">Comparison operators</a>
  template&lt;typename charT, typename traits&gt;
  bool <a href="#strings.string_ref.operator==">operator==</a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);
  template&lt;typename charT, typename traits&gt;
  bool <a href="#strings.string_ref.operator!=">operator!=</a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);
  template&lt;typename charT, typename traits&gt;
  bool <a href="#strings.string_ref.operator&lt;">operator&lt;</a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);
  template&lt;typename charT, typename traits&gt;
  bool <a href="#strings.string_ref.operator>">operator&gt;</a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);
  template&lt;typename charT, typename traits&gt;
  bool <a href="#strings.string_ref.operator&lt;=">operator&lt;=</a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);
  template&lt;typename charT, typename traits&gt;
  bool <a href="#strings.string_ref.operator>=">operator&gt;=</a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);

  // Inserter
  template&lt;class charT, class traits>
  basic_ostream&lt;charT, traits>&amp;
  <a href="#strings.string_ref.operator&lt;&lt;">operator&lt;&lt;</a>(basic_ostream&lt;charT, traits>&amp; os,
             const basic_string_ref&lt;charT,traits>&amp; str);

  // <a href="#strings.string_ref.hash">Hashing</a>
  template&lt;> struct hash&lt;string_ref>;
  template&lt;> struct hash&lt;u16string_ref>;
  template&lt;> struct hash&lt;u32string_ref>;
  template&lt;> struct hash&lt;wstring_ref>;
}
}</code></pre>

      <section class="numbered">
        <header><h4 id="strings.string_ref.cons"><span
        class="sectnum">?.2.1</span> basic_string_ref constructors,
        assignment, and conversions <span
        class="sectname">[strings.string_ref.cons]</span></h4></header>

        <section class="function">
          <header><code id="strings.string_ref.cons()">constexpr <a href="#strings.string_ref.cons()">basic_string_ref</a>();
          </code></header>

          <dl class="attribute">
            <dt>Postconditions:</dt><dd><code>empty() == true</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.cons(string_ref)">constexpr <a href="#strings.string_ref.cons(string_ref)">basic_string_ref</a>(const basic_string_ref&amp; other);
          </code></header>

          <dl class="attribute">
            <dt>Postconditions:</dt><dd><code>data() == other.data() &amp;&amp;<wbr/>
            size() == other.size()</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.assign">basic_string_ref&amp; <a href="#strings.string_ref.assign">operator=</a>(const basic_string_ref&amp; other);
          </code></header>

          <dl class="attribute">
            <dt>Postconditions:</dt><dd><code>data() == other.data() &amp;&amp;<wbr/>
            size() == other.size()</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.cons(charT*)"><a href="#strings.string_ref.cons(charT*)">basic_string_ref</a>(const charT* str);
          </code></header>

          <dl class="attribute">
            <dt>Postconditions:</dt><dd><code><a
            href="#strings.string_ref.data">data()</a> == str</code>, and
            <code>size()</code> is <code>0</code> if <code>str == nullptr</code>
            or <code>strlen(str)</code> otherwise.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.cons(string)">template&lt;typename Allocator&gt;
          <a href="#strings.string_ref.cons(string)">basic_string_ref</a>(const basic_string&lt;charT, traits, Allocator&gt;&amp; str);
          </code></header>

          <dl class="attribute">
            <dt>Postconditions:</dt><dd><code><a
            href="#strings.string_ref.data">data()</a> == str.data() &amp;&amp;<wbr/>
            <a href="#strings.string_ref.size">size()</a> ==
            str.size()</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.cons(charT*,len)">constexpr <a href="#strings.string_ref.cons(charT*,len)">basic_string_ref</a>(const charT* str, size_type len);
          </code></header>

          <dl class="attribute">
            <dt>Postconditions:</dt><dd><code><a
            href="#strings.string_ref.data">data()</a> == str &amp;&amp;<wbr/> size()
            == len</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.cons(init_list)"><a href="#strings.string_ref.cons(init_list)">basic_string_ref</a>(initializer_list&lt;charT> il);
          </code></header>

          <dl class="attribute">
            <dt>Postconditions:</dt><dd><code><a
            href="#strings.string_ref.data">data()</a> == il.begin() &amp;&amp;<wbr/>
            size() == il.size()</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.operator.basic_string">template&lt;typename Allocator&gt;
          explicit <a href="#strings.string_ref.operator.basic_string">operator basic_string&lt;charT, traits, Allocator&gt;</a>() const;
          </code></header>

          <dl
          class="attribute"><dt>Returns:</dt><dd><code>basic_string&lt;charT,
          traits, Allocator&gt;(data(), size())</code>.</dd></dl>

          <p>[Note: The operator is <code>explicit</code> to avoid accidental
          O(N) operations on type mismatches. &#8212; end note]</p>
        </section>
      </section>

      <section class="numbered">
        <header><h4 id="strings.string_ref.iterators"><span
        class="sectnum">?.2.2</span> basic_string_ref iterator support <span
        class="sectname">[strings.string_ref.iterators]</span></h4></header>

        <section class="function">
          <header><code id="strings.string_ref.const_iterator">typedef <var>implementation_defined</var> <a href="#strings.string_ref.const_iterator">const_iterator</a>;</code></header>

          <p>A random-access, contiguous iterator type.</p>

          <p>For a <code>string_ref <var>str</var></code>, any operation that
          invalidates a pointer in the range
          [<code><var>str</var>.data()</code>,
          <code><var>str</var>.data+<var>str</var>.size()</code>) invalidates
          pointers and iterators returned from <code><var>str</var></code>'s
          methods.</p>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.iterator">typedef const_iterator <a href="#strings.string_ref.iterator">iterator</a>;</code></header>

          <p>Because <code>string_ref</code> refers to a constant sequence,
          <code>iterator</code> and <code>const_iterator</code> are the same
          type. </p>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.begin">constexpr const_iterator <a href="#strings.string_ref.begin">begin</a>() const;<br/>
          constexpr const_iterator cbegin() const;</code></header>
          <dl class="attribute">
            <dt>Returns:</dt><dd>An iterator referring to the first character in the string.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.end">constexpr const_iterator <a href="#strings.string_ref.end">end</a>() const;<br/>
          constexpr const_iterator cend() const;</code></header>
          <dl class="attribute">
            <dt>Returns:</dt><dd>An iterator which is the past-the-end value.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.rbegin">const_reverse_iterator <a href="#strings.string_ref.rbegin">rbegin</a>() const;<br/>
          const_reverse_iterator crbegin() const;</code></header>
          <dl class="attribute">
            <dt>Returns:</dt><dd>An iterator which is semantically equivalent to
            <code>reverse_iterator(end())</code>.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.rend">const_reverse_iterator <a href="#strings.string_ref.rend">rend</a>() const;<br/>
          const_reverse_iterator crend() const;</code></header>
          <dl class="attribute">
            <dt>Returns:</dt><dd>An iterator which is semantically equivalent to
            <code>reverse_iterator(begin())</code>.</dd>
          </dl>
        </section>
      </section>

      <section class="numbered">
        <header><h4 id="strings.string_ref.capacity"><span class="sectnum">?.2.3</span> basic_string_ref capacity <span class="sectname">[strings.string_ref.capacity]</span></h4></header>

        <section class="function">
          <header><code id="strings.string_ref.size">constexpr size_type <a href="#strings.string_ref.size">size</a>() const;</code><br/>
          <code>constexpr size_type length() const;</code></header>
          <dl class="attribute">
            <dt>Returns:</dt><dd><code>std::distance(begin(), end())</code>, a count
            of the number of char-like objects currently in the string.</dd>
            <dt>Complexity:</dt><dd>constant time.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.max_size">constexpr size_type <a href="#strings.string_ref.max_size">max_size</a>() const;</code></header>
          <dl class="attribute">
            <dt>Returns:</dt><dd>The size of the largest possible string.</dd>
            <dt>Complexity:</dt><dd>constant time.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.empty">constexpr bool <a href="#strings.string_ref.empty">empty</a>() const;</code></header>
          <dl class="attribute">
            <dt>Returns:</dt><dd><code>size() == 0</code></dd>
          </dl>
        </section>
      </section>

      <section class="numbered">
        <header><h4 id="strings.string_ref.access"><span
        class="sectnum">?.2.4</span> basic_string element access <span
        class="sectname">[strings.string_ref.access]</span></h4></header>

        <section class="function">
          <header><code id="strings.string_ref.operator.index">constexpr const charT&amp; <a href="#strings.string_ref.operator.index">operator[]</a>(size_type pos) const;</code></header>
          <dl class="attribute">
            <dt>Requires:</dt><dd><code>pos &lt; size()</code></dd>
            <dt>Throws:</dt><dd>Nothing</dd>
            <dt>Returns:</dt><dd><code>*(begin() + pos)</code></dd>
            <dt>Complexity:</dt><dd>constant time.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.at">constexpr const charT&amp; <a href="#strings.string_ref.at">at</a>(size_type pos) const;</code></header>
          <dl class="attribute">
            <dt>Throws:</dt><dd><code>out_of_range</code> if <code>pos >=
            size()</code>.</dd>
            <dt>Returns:</dt><dd><code>operator[](pos)</code></dd>
            <dt>Complexity:</dt><dd>constant time.</dd>
          </dl>
        </section>
    
        <section class="function">
          <header><code id="strings.string_ref.front">constexpr const charT&amp; <a href="#strings.string_ref.front">front</a>() const;</code></header>
          <dl class="attribute">
            <dt>Requires:</dt><dd><code>!empty()</code></dd>
            <dt>Throws:</dt><dd>Nothing</dd>
            <dt>Returns:</dt><dd><code>operator[](0)</code></dd>
          </dl>
        </section>
    
        <section class="function">
          <header><code id="strings.string_ref.back">constexpr const charT&amp; <a href="#strings.string_ref.back">back</a>() const;</code></header>
          <dl class="attribute">
            <dt>Requires:</dt><dd><code>!empty()</code></dd>
            <dt>Throws:</dt><dd>Nothing</dd>
            <dt>Returns:</dt><dd><code>operator[](size() - 1)</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.data">constexpr const charT* <a href="#strings.string_ref.data">data</a>() const;
          </code></header>

          <dl class="attribute">
            <dt>Returns:</dt><dd>A pointer <code>p</code> such that
            <code>p + i == &amp;operator[](i)</code> for each <code>i</code> in
            <code>[0,size())</code>.  The range [<code><a
            href="#strings.string_ref.data">data()</a></code>,<code><a
            href="#strings.string_ref.data">data()</a> + size()</code>) must be
            valid even for empty <code>basic_string_ref</code>s..</dd>
            <dt>Complexity:</dt><dd>constant time.</dd>
            <dt>Requires:</dt><dd>The program shall not alter any of the values
            stored in the character array.</dd>
          </dl>
        </section>
      </section>

      <section class="numbered">
        <header><h4 id="strings.string_ref.modifiers"><span
        class="sectnum">?.2.5</span> basic_string_ref modifiers <span
        class="sectname">[strings.string_ref.modifiers]</span></h4></header>

        <section class="function">
          <header><code id="strings.string_ref.clear">void <a href="#strings.string_ref.clear">clear</a>();</code></header>

          <dl class="attribute">
            <dt>Effects:</dt><dd><code>*this = basic_string_ref()</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.remove_prefix">void <a href="#strings.string_ref.remove_prefix">remove_prefix</a>(size_type n);</code></header>

          <dl class="attribute">
            <dt>Effects:</dt><dd><code>*this = <a href="#strings.string_ref.substr">substr</a>(n, npos);</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.remove_suffix">void <a href="#strings.string_ref.remove_suffix">remove_suffix</a>(size_type n);
          </code></header>

          <dl class="attribute">
            <dt>Effects:</dt><dd><code>*this = <a href="#strings.string_ref.substr">substr</a>(0, size() - n)</code></dd>
          </dl>
        </section>
      </section>

      <section class="numbered">
        <header><h4 id="strings.string_ref.ops"><span
        class="sectnum">?.2.6</span> basic_string_ref string operations <span
        class="sectname">[strings.string_ref.ops]</span></h4></header>

        <p>Unlike std::string, string_ref provides no whole-string methods with <code>position</code> or <code>length</code> parameters. Instead, users should use the <code><a href="#strings.string_ref.substr">substr()</a></code> method to create the character sequence they're actually interested in, and use that.</p>

        <section class="numbered">
          <header><h5 id="strings.string_ref.ops.substr"><span
          class="sectnum">?.2.6.1</span> substr <span
          class="sectname">[strings.string_ref.ops.substr]</span></h5></header>

          <section class="function">
            <header><code id="strings.string_ref.substr">constexpr basic_string_ref <a href="#strings.string_ref.substr">substr</a>(size_type pos, size_type len=npos) const;
            </code></header>

            <dl class="attribute">
              <dt>Throws:</dt><dd><code>out_of_range</code> if <code>pos > size()</code>.</dd>

              <dt>Effects:</dt><dd>Determines the effective length
              <code><var>rlen</var></code> of the string to copy as the smaller of
              <code>len</code> and <code>size() - pos</code>.</dd>

              <dt>Returns:</dt><dd><code><a href="#strings.string_ref.cons(charT*,len)">basic_string_ref</a>(data()+pos, <var>rlen</var>)</code>.</dd>
            </dl>
          </section>
        </section>

        <section class="numbered">
          <header><h5 id="strings.string_ref.ops.comparison"><span
          class="sectnum">?.2.6.2</span> comparisons <span
          class="sectname">[strings.string_ref.ops.comparison]</span></h5></header>

          <section class="function">
            <header><code id="strings.string_ref.compare">int <a href="#strings.string_ref.compare">compare</a>(basic_string_ref other) const;</code></header>

            <dl class="attribute">
              <dt>Effects:</dt><dd>Determines the effective length
              <code><var>rlen</var></code> of the strings to compare as the
              smallest of <code>size()</code> and <code>other.size()</code>. The
              function then compares the two strings by calling
              <code>traits::compare(data(), other.data(),
              <var>rlen</var>)</code>.</dd>

              <dt>Returns:</dt><dd>The nonzero result if the result of the
              comparison is nonzero. Otherwise, returns a value as indicated in the following table:
              <table>
                <caption>compare() results</caption>
                <tr><th>Condition</th><th>Return Value</th></tr>
                <tr><td><code>size() &lt;&#xA0; str.size()</code></td><td><code>&lt; 0</code></td></tr>
                <tr><td><code>size() == str.size()</code></td><td><code>&#xA0; 0</code></td></tr>
                <tr><td><code>size() >&#xA0; str.size()</code></td><td><code>> 0</code></td></tr>
              </table></dd>
            </dl>
          </section>

          <section class="function">
            <header><code id="strings.string_ref.starts_with">bool <a href="#strings.string_ref.starts_with">starts_with</a>(basic_string_ref x) const;
            </code></header>

            <dl class="attribute">
              <dt>Returns:</dt><dd><code>true</code> if <code>x</code> is a prefix of <code>*this</code>.</dd>
            </dl>
          </section>

          <section class="function">
            <header><code id="strings.string_ref.ends_with">bool <a href="#strings.string_ref.ends_with">ends_with</a>(basic_string_ref x) const;</code></header>

            <dl class="attribute">
              <dt>Returns:</dt><dd><code>true</code> if <code>x</code> is a suffix of <code>*this</code>.</dd>
            </dl>
          </section>
        </section>

        <section class="numbered">
          <header><h5 id="strings.string_ref.ops.search"><span
          class="sectnum">?.2.6.3</span> searching <span
          class="sectname">[strings.string_ref.ops.search]</span></h5></header>

          <p>All member functions in this section that take a <code>charT</code>
          argument <code><var>c</var></code> return the result of a call to the
          same-named member function with an argument of
          <code>basic_string_ref(&amp;c, 1)</code>.</p>

          <section class="function">
            <header><code id="strings.string_ref.find">size_type <a href="#strings.string_ref.find">find</a>(basic_string_ref str) const;<br/>
            size_type find(charT c) const;</code></header>

            <dl class="attribute">
              <dt>Effects:</dt><dd>Determines the lowest position
              <code><var>xpos</var></code>, if possible, such that both of the
              following conditions obtain:
              <ul>
                <li><code><var>xpos</var> + str.size() &lt;= size()</code></li>

                <li><code>traits::eq(at(<var>xpos</var>+I), str.at(I))</code>
                for all elements <code>I</code> of the string referenced by
                <code>str</code>.</li>
              </ul></dd>

              <dt>Returns:</dt><dd><var>xpos</var> if the function can determine
              such a value for <var>xpos</var>. Otherwise, returns
              <code>npos</code>.</dd>

              <dt>Remarks:</dt><dd>Uses <code>traits::eq()</code>.</dd>
            </dl>
          </section>

          <section class="function">
            <header><code id="strings.string_ref.rfind">size_type <a href="#strings.string_ref.rfind">rfind</a>(basic_string_ref str) const;<br/>
            size_type rfind(charT c) const;</code></header>

            <dl class="attribute">
              <dt>Effects:</dt><dd>Determines the highest position
              <code><var>xpos</var></code>, if possible, such that both of the
              following conditions obtain:
              <ul>
                <li><code><var>xpos</var> + str.size() &lt;= size()</code></li>
                <li><code>traits::eq(at(<var>xpos</var>+I), str.at(I))</code>
                for all elements <code>I</code> of the string referenced by
                <code>str</code>.</li>
              </ul></dd>

              <dt>Returns:</dt><dd><code><var>xpos</var></code> if the function
              can determine such a value for
              <code><var>xpos</var></code>. Otherwise, returns
              <code>npos</code>.</dd>

              <dt>Remarks:</dt><dd>Uses <code>traits::eq()</code>.</dd>
            </dl>
          </section>

          <section class="function">
            <header><code id="strings.string_ref.find_first_of">size_type <a href="#strings.string_ref.find_first_of">find_first_of</a>(basic_string_ref str) const;<br/>
          size_type find_first_of(charT c) const;</code></header>

            <dl class="attribute">
              <dt>Effects:</dt><dd>Determines the lowest position
              <code><var>xpos</var></code>, if possible, such that both of the
              following conditions obtain:
              <ul>
                <li><code><var>xpos</var> &lt;= size()</code></li>
                <li><code>traits::eq(at(<var>xpos</var>+I), str.at(I))</code>
                for some element <code>I</code> of the string referenced by
                <code>str</code>.</li>
              </ul></dd>

              <dt>Returns:</dt><dd><code><var>xpos</var></code> if the function
              can determine such a value for
              <code><var>xpos</var></code>. Otherwise, returns
              <code>npos</code>.</dd>

              <dt>Remarks:</dt><dd>Uses <code>traits::eq()</code>.</dd>
            </dl>
          </section>

          <section class="function">
            <header><code id="strings.string_ref.find_last_of">size_type <a href="#strings.string_ref.find_last_of">find_last_of</a>(basic_string_ref str) const;<br/>
          size_type find_last_of(charT c) const;</code></header>

            <dl class="attribute">
              <dt>Effects:</dt><dd>Determines the highest position
              <code><var>xpos</var></code>, if possible, such that both of the
              following conditions obtain:
              <ul>
                <li><code><var>xpos</var> &lt;= size()</code></li>
                <li><code>traits::eq(at(<var>xpos</var>+I), str.at(I))</code>
                for some element <code>I</code> of the string referenced by
                <code>str</code>.</li>
              </ul></dd>

              <dt>Returns:</dt><dd><code><var>xpos</var></code> if the function
              can determine such a value for
              <code><var>xpos</var></code>. Otherwise, returns
              <code>npos</code>.</dd>

              <dt>Remarks:</dt><dd>Uses <code>traits::eq()</code>.</dd>
            </dl>
          </section>

          <section class="function">
            <header><code id="strings.string_ref.find_first_not_of">size_type <a href="#strings.string_ref.find_first_not_of">find_first_not_of</a>(basic_string_ref str) const;<br/>
            size_type find_first_not_of(charT c) const;</code></header>

            <dl class="attribute">
              <dt>Effects:</dt><dd>Determines the lowest position
              <code><var>xpos</var></code>, if possible, such that both of the
              following conditions obtain:
              <ul>
                <li><code><var>xpos</var> &lt;= size()</code></li>
                <li><code>traits::eq(at(<var>xpos</var>+I), str.at(I))</code>
                for no element <code>I</code> of the string referenced by
                <code>str</code>.</li>
              </ul></dd>

              <dt>Returns:</dt><dd><code><var>xpos</var></code> if the function
              can determine such a value for
              <code><var>xpos</var></code>. Otherwise, returns
              <code>npos</code>.</dd>

              <dt>Remarks:</dt><dd>Uses <code>traits::eq()</code>.</dd>
            </dl>
          </section>

          <section class="function">
            <header><code id="strings.string_ref.find_last_not_of">size_type <a href="#strings.string_ref.find_last_not_of">find_last_not_of</a>(basic_string_ref str) const;<br/>
            size_type find_last_not_of(charT c) const;</code></header>

            <dl class="attribute">
              <dt>Effects:</dt><dd>Determines the highest position
              <code><var>xpos</var></code>, if possible, such that both of the
              following conditions obtain:
              <ul>
                <li><code><var>xpos</var> &lt;= size()</code></li>
                <li><code>traits::eq(at(<var>xpos</var>+I), str.at(I))</code>
                for no element <code>I</code> of the string referenced by
                <code>str</code>.</li>
              </ul></dd>

              <dt>Returns:</dt><dd><code><var>xpos</var></code> if the function
              can determine such a value for
              <code><var>xpos</var></code>. Otherwise, returns
              <code>npos</code>.</dd>

              <dt>Remarks:</dt><dd>Uses <code>traits::eq()</code>.</dd>
            </dl>
          </section>
        </section>
      </section>

      <section class="numbered">
        <header><h4 id="strings.string_ref.nonmem.compare"><span
        class="sectnum">?.2.7</span> basic_string_ref non-member comparison
        operators <span
        class="sectname">[strings.string_ref.nonmem.compare]</span></h4></header>

        <section class="function">
          <header><code id="strings.string_ref.operator==">template&lt;typename charT, typename traits&gt;<br/>
          bool <a href="#strings.string_ref.operator==">operator==</a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);</code></header>

          <dl class="attribute">
            <dt>Returns:</dt><dd><code>x.compare(y) == 0</code></dd>

            <dt>Remarks:</dt><dd>Equality can be implemented faster than comparison.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.operator!=">template&lt;typename charT, typename traits&gt;<br/>
          bool <a href="#strings.string_ref.operator!=">operator!=</a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);</code></header>

          <dl class="attribute">
            <dt>Returns:</dt><dd><code>x.compare(y) != 0</code></dd>

            <dt>Remarks:</dt><dd>Inequality can be implemented faster than comparison.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.operator&lt;">template&lt;typename charT, typename traits&gt;<br/>
          bool <a href="#strings.string_ref.operator&lt;">operator&lt;</a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);</code></header>

          <dl class="attribute">
            <dt>Returns:</dt><dd><code>x.compare(y) &lt; 0</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.operator>">template&lt;typename charT, typename traits&gt;<br/>
          bool <a href="#strings.string_ref.operator>">operator></a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);</code></header>

          <dl class="attribute">
            <dt>Returns:</dt><dd><code>x.compare(y) > 0</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.operator&lt;=">template&lt;typename charT, typename traits&gt;<br/>
          bool <a href="#strings.string_ref.operator&lt;=">operator&lt;=</a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);</code></header>

          <dl class="attribute">
            <dt>Returns:</dt><dd><code>x.compare(y) &lt;= 0</code></dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.string_ref.operator>=">template&lt;typename charT, typename traits&gt;<br/>
          bool <a href="#strings.string_ref.operator>=">operator&gt;=</a>(basic_string_ref&lt;charT, traits&gt; x, basic_string_ref&lt;charT, traits&gt; y);</code></header>

          <dl class="attribute">
            <dt>Returns:</dt><dd><code>x.compare(y) >= 0</code></dd>
          </dl>
        </section>
      </section>

      <section class="numbered">
        <header><h4 id="strings.string_ref.io"><span
        class="sectnum">?.2.8</span> basic_string_ref inserter <span
        class="sectname">[strings.string_ref.io]</span></h4></header>

        <section class="function">
          <header><code id="strings.string_ref.operator&lt;&lt;">template&lt;class charT, class traits><br/>
  basic_ostream&lt;charT, traits>&amp;<br/>
<a href="#strings.string_ref.operator&lt;&lt;">operator&lt;&lt;</a>(basic_ostream&lt;charT, traits>&amp; os,<br/>
           const basic_string_ref&lt;charT,traits>&amp; str);</code></header>

          <dl class="attribute">
            <dt>Effects:</dt><dd>Behaves as a formatted output function
            (27.7.3.6.1). After constructing a <code>sentry</code> object, if
            this object returns <code>true</code> when converted to a value of
            type <code>bool</code>, determines padding as described in
            22.4.2.2.2, then inserts the resulting sequence of characters
            <code>seq</code> as if by calling <code>os.rdbuf()->sputn(seq,
            <var>n</var>)</code>, where <code><var>n</var></code> is the larger
            of <code>os.width()</code> and <code>str.size()</code>; then calls
            <code>os.width(0)</code>.</dd>

            <dt>Returns:</dt><dd>os</dd>
          </dl>
        </section>
      </section>

      <section class="numbered">
        <header><h4 id="strings.string_ref.hash"><span
        class="sectnum">?.2.9</span> basic_string_ref hash <span
        class="sectname">[strings.string_ref.hash]</span></h4></header>

        <section class="function">
          <header><code>template&lt;> struct hash&lt;string_ref>;<br/>
          template&lt;> struct hash&lt;u16string_ref>;<br/>
          template&lt;> struct hash&lt;u32string_ref>;<br/>
          template&lt;> struct hash&lt;wstring_ref>;</code></header>

          <dl class="attribute">
            <dt>Requires:</dt><dd>the template specializations shall meet the
            requirements of class template hash</dd>
          </dl>
        </section>
      </section>
    </section>

    <section class="numbered">
      <header><h3 id="strings.conversions.numeric"><span
      class="sectnum">?.3</span> Numeric conversions <span
      class="sectname">[strings.conversions.numeric]</span></h3></header>

      <p>[Note: The functions below mirror C++11's
      <code>sto<var>x</var>()</code> functions on strings.  Because
      <code>string_ref</code> can cheaply change to refer to a smaller
      substring, we should also add a more convenient interface that advances
      the <code>string_ref</code> as it parses an integer out, with the rough
      signature <code>sto<var>x</var>_consume(string_ref&amp;, int
      base=10)</code>. However, failure is expected in parsing functions, so
      it's not appropriate to raise an exception when no integer is available to
      be parsed.  Existing practice is to use a signature like <code>bool
      sto<var>x</var>_consume(string_ref&amp;, T&amp; result, int
      base=10)</code>, but this requires a temporary integral variable to store
      the result in.  If we get an <code>optional&lt;T></code> type in a TS, a
      better signature along the lines of <code>optional&lt;T>
      sto<var>x</var>_consume(string_ref&amp;, int base=10)</code> becomes
      available.  To avoid precluding the <code>optional</code> signature, I
      haven't included any of the <code>consume</code> variants in this
      paper. &#8212; end note]</p>

      <section class="function">
          <header><code id="strings.stox">int <a href="#strings.stox">stoi</a>(const string_ref&amp; str, size_t* idx=0, int base=10);<br/>
          long stol(const string_ref&amp; str, size_t* idx=0, int base=10);<br/>
          unsigned long stoul(const string_ref&amp; str, size_t* idx=0, int base=10);<br/>
          long long stoll(const string_ref&amp; str, size_t* idx=0, int base=10);<br/>
          unsigned long long stoull(const string_ref&amp; str, size_t* idx=0, int base=10);</code></header>

          <dl class="attribute">
            <dt>Returns:</dt><dd><code>sto<var>x</var>(string(str), idx,
            base)</code> where <code><var>x</var></code> is the type suffix of
            the function called.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.stof">float <a href="#strings.stof">stof</a>(const string_ref&amp; str, size_t* idx=0);<br/>
          double stod(const string_ref&amp; str, size_t* idx=0);<br/>
          long double stold(const string_ref&amp; str, size_t* idx=0);</code></header>

          <dl class="attribute">
            <dt>Returns:</dt><dd><code>sto<var>x</var>(string(str), idx)</code>
            where <code><var>x</var></code> is the type suffix of the function
            called.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.wstox">int <a href="#strings.wstox">stoi</a>(const wstring_ref&amp; str, size_t* idx=0, int base=10);<br/>
  long stol(const wstring_ref&amp; str, size_t* idx=0, int base=10);<br/>
  unsigned long stoul(const wstring_ref&amp; str, size_t* idx=0, int base=10);<br/>
  long long stoll(const wstring_ref&amp; str, size_t* idx=0, int base=10);<br/>
  unsigned long long stoull(const wstring_ref&amp; str, size_t* idx=0, int base=10);</code></header>
          <dl class="attribute">
            <dt>Returns:</dt><dd><code>sto<var>x</var>(wstring(str), idx,
            base)</code> where <code><var>x</var></code> is the type suffix of
            the function called.</dd>
          </dl>
        </section>

        <section class="function">
          <header><code id="strings.wstof">float <a href="#strings.wstof">stof</a>(const wstring_ref&amp; str, size_t* idx=0);<br/>
  double stod(const wstring_ref&amp; str, size_t* idx=0);<br/>
  long double stold(const wstring_ref&amp; str, size_t* idx=0);</code></header>

          <dl class="attribute">
            <dt>Returns:</dt><dd><code>sto<var>x</var>(wstring(str), idx)</code>
            where <code><var>x</var></code> is the type suffix of the function
            called.</dd>
          </dl>
        </section>
    </section>
  </section>

  <hr/>

  <section>
    <header><h2 id="future">Future work outside the scope of a TS</h2></header>
    <ul>
      <li><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.</li>

      <li>Consider replacing these conversion operators with new constructor overloads on the target types.</li>

      <li>Consider adding <code>starts_with</code> and <code>ends_with</code> methods to <code>basic_string</code>.</li>
    </ul>

  </section>
</body>
</html>
