
<!-- saved from url=(0068)http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>String Prefix and Suffix Checking</title>
</head>
<body>

<table>
  <tbody><tr>
    <td width="172" align="left" valign="top">Document number:</td>
    <td width="435">P0457R2</td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Date:</td>
    <td width="435">2017-11-11</td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Project:</td>
    <td width="435">LWG</td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Reply-to:</td>
    <td width="435">Mikhail Maltsev
        &lt;<a href="mailto:maltsevm@gmail.com">maltsevm@gmail.com</a>&gt;</td>
  </tr>
</tbody></table>

<h1>String Prefix and Suffix Checking</h1>

<p></p><ol>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#abstract">Abstract</a></li>
  <li>
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#history">History</a>
    <ol>
      <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#history-r0">Changes from R0</a></li>
      <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#history-r0">Changes from R1</a></li>
    </ol>
  </li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#motivation">Motivation</a></li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#prior">Prior work</a></li>
  <li>
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#design">Design considerations</a>
    <ol>
      <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#design-member">Member function vs free function</a></li>
      <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#design-overload">Overload set</a></li>
      <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#design-byref">Passing by value vs passing by reference</a></li>
    </ol>
  </li>
  <li>
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#wording">Wording</a>
    <ol>
      <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#wording-string">basic_string</a></li>
      <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#wording-string_view">basic_string_view</a></li>
    </ol>
  </li>
  <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#references">References</a></li>
</ol><p></p>

<h2><a name="abstract">1. Abstract</a></h2>
<p>This paper proposes to add member functions <tt>starts_with</tt> and
<tt>ends_with</tt> to class templates <tt>basic_string</tt> and
<tt>basic_string_view</tt>. These functions check, whether or not a string
starts with a given prefix or ends with a given suffix, respectively.</p>


<h2><a name="history">2. History</a></h2>
<h3><a name="hist-r0">2.1. Changes from R0</a></h3>
<p></p><ul>
  <li>Overloads accepting <tt>const charT*</tt> were added</li>
  <li>
    Behaviour of all operations (except the two mentioned below) was expressed in terms of
    the following two methods of the <tt>basic_string_view</tt> template:
    <ul>
      <li><tt>constexpr bool starts_with(basic_string_view&lt;charT, traits&gt; s) const noexcept;</tt></li>
      <li><tt>constexpr bool ends_with(basic_string_view&lt;charT, traits&gt; s) const noexcept;</tt></li>
    </ul>
  </li>
</ul><p></p>
<h3><a name="hist-r0">2.1. Changes from R1</a></h3>
<p></p><ul>
  <li>Dropped <tt>noexcept</tt> for <tt>const charT*</tt> overloads</li>
  <li>More concise wording</li>
</ul><p></p>

<h2><a name="motivation">3. Motivation</a></h2>
<p>Checking, whether or not a given string starts with a
given prefix (or ends with a given suffix) is a common task. In fact, standard
libraries of many other programming languages include routines for performing
such checks, for example:</p>

<p></p><ul>
  <li>
    Python: <tt>str</tt> and <tt>unicode</tt> classes have <tt>startswith</tt>
    and <tt>endswith</tt> methods [<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#ref1">1</a>].
  </li>
  <li>
    Java: class <tt>String</tt> has <tt>startsWith</tt> and <tt>endsWith</tt>
    methods [<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#ref2">2</a>].
  </li>
</ul><p></p>

<p>And so on.</p>

<p>Also, some C++ libraries (other than the standard library) that implement a
string type include such methods. For example, Qt  library has classes
<tt>QString</tt> [<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#ref3">3</a>] and <tt>QStringRef</tt> (analogous to
<tt>std::string_view</tt>) which have <tt>startsWith</tt> and
<tt>endsWith</tt> member functions.</p>

<p>These functions are widely used. For example, the source code of a recent
version of Qt (excluding third-party components) has 1193 occurrences of
<tt>startsWith</tt> and 953 occurrences of <tt>endsWith</tt>. Other examples
include Webkit (304 occurrences of <tt>startsWith</tt> and 142 occurrences of
<tt>endsWith</tt>) and LLVM (class <tt>StringRef</tt>, 113 matches for
<tt>StartsWith</tt> and 38 matches for <tt>EndsWith</tt>).</p>

<h2><a name="prior">4. Prior work</a></h2>

<p>The <tt>basic_string_view</tt> class template  included <tt>starts_with</tt>
and <tt>ends_with</tt> up to revision 3 of the proposal (N3609
[<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#ref4">4</a>]). These two member functions were removed after LEWG
discussion in Bristol. The main concerns were:</p>

<p></p><ul>
  <li><tt>basic_string_view</tt> should have an API consistent with <tt>basic_string</tt>;</li>
  <li>changes to <tt>basic_string</tt> should go to a separate proposal.</li>
</ul><p></p>

<h2><a name="design">5. Design considerations</a></h2>

<h3><a name="design-member">5.1. Member function vs free function</a></h3>

<p>This proposal adds member functions <tt>starts_with</tt> and
<tt>ends_with</tt> to class templates <tt>basic_string</tt> and
<tt>basic_string_view</tt>. Another considered option was to add free functions
to namespace std, but adding member functions is consistent with the existing
API for <tt>compare</tt>. Besides, as the original proposal [<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#ref5">5</a>]
mentioned, the order of parameters of a free function is
ambiguous (<tt>starts_with(string, prefix)</tt> vs <tt>starts_with(prefix,
string)</tt>).</p>

<h3><a name="design-overload">5.2. Overload set</a></h3>

<p>The original string_view proposal included the following overloads of
<tt>starts_with</tt>:</p>

<pre>// basic_string:
bool starts_with(basic_string_view&lt;charT, traits&gt; s) const noexcept;
bool starts_with(charT c) const noexcept;
bool starts_with(const charT* s) const noexcept;

// basic_string_view:
bool starts_with(const basic_string_view&amp; prefix) const noexcept;
</pre>

<p>Qt offers the following overload set (for <tt>QString</tt> and
<tt>QStringRef</tt>):</p>

<pre>bool startsWith(const QString &amp; s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
bool startsWith(const QLatin1String &amp; s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
bool startsWith(const QChar &amp; c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
bool startsWith(const QStringRef &amp; s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
</pre>

<p>This proposal includes the following overloads:</p>

<pre>// basic_string:
bool starts_with(charT x) const noexcept;
bool starts_with(basic_string_view&lt;charT, traits&gt; x) const noexcept;
bool starts_with(const charT* x) const;

// basic_string_view:
constexpr bool starts_with(charT x) const noexcept;
constexpr bool starts_with(basic_string_view&lt;charT, traits&gt; x) const noexcept;
constexpr bool starts_with(const charT* x) const;
</pre>

<p>The overload overload for <tt>basic_string</tt> is not included, because
<tt>basic_string</tt> has a non-explicit conversion operator to
<tt>basic_string_view</tt>.</p>

<h3><a name="design-byref">5.3. Passing by value vs passing by reference</a></h3>

<p>In accordance with the guidance from P0254R1 [<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0457r1.html#ref5">5</a>],
objects of type <tt>basic_string_view</tt> are passed by value (not by reference).</p>

<h2><a name="wording">6. Wording</a></h2>

<h3><a name="wording-string">6.1. basic_string</a></h3>

<p>In [basic.string], add:</p>

<pre>bool starts_with(basic_string_view&lt;charT, traits&gt; x) const noexcept;
bool starts_with(charT x) const noexcept;
bool starts_with(const charT* x) const;
bool ends_with(basic_string_view&lt;charT, traits&gt; x) const noexcept;
bool ends_with(charT x) const noexcept;
bool ends_with(const charT* x) const;
</pre>

<p>After [string::compare] add:</p>

<p><b>basic_string::starts_with [string.starts_with]</b></p>

<pre>bool starts_with(basic_string_view&lt;charT, traits&gt; x) const noexcept;
bool starts_with(charT x) const noexcept;
bool starts_with(const charT* x) const;</pre>
<p>Effects: Equivalent to:
<tt>return basic_string_view&lt;charT, traits&gt;(data(), size()).starts_with(x);</tt><br>
</p>

<p><b>basic_string::ends_with [string.ends_with]</b></p>

<pre>bool ends_with(basic_string_view&lt;charT, traits&gt; x) const noexcept;
bool ends_with(charT x) const noexcept;
bool ends_with(const charT* x) const;</pre>
<p>Effects: Equivalent to:
<tt>return basic_string_view&lt;charT, traits&gt;(data(), size()).ends_with(x);</tt><br>
</p>

<h3><a name="wording-string_view">6.2. basic_string_view</a></h3>

<p>In [string.view.template], add:</p>

<pre>constexpr bool starts_with(basic_string_view x) const noexcept;
constexpr bool starts_with(charT x) const noexcept;
constexpr bool starts_with(const charT* x) const;
constexpr bool ends_with(basic_string_view x) const noexcept;
constexpr bool ends_with(charT x) const noexcept;
constexpr bool ends_with(const charT* x) const;
</pre>

<p>In [string.view.ops], add:</p>

<pre>constexpr bool starts_with(basic_string_view x) const noexcept;
</pre>
<p>Effects: Equivalent to: <tt>return compare(0, npos, x) == 0;</tt></p>

<pre>constexpr bool starts_with(charT x) const noexcept;
</pre>
<p>Effects: Equivalent to: <tt>return starts_with(basic_string_view(&amp;x, 1));</tt></p>

<pre>constexpr bool starts_with(const charT* x) const;
</pre>
<p>Effects: Equivalent to: <tt>return starts_with(basic_string_view(x));</tt></p>

<pre>constexpr bool ends_with(basic_string_view x) const noexcept;
</pre>
<p>Effects: Equivalent to:
<tt>return size() &gt;= x.size() &amp;&amp; compare(size() - x.size(), npos, x) == 0;</tt></p>

<pre>constexpr bool ends_with(charT x) const noexcept;
</pre>
<p>Effects: Equivalent to:
<tt>return ends_with(basic_string_view(&amp;x, 1));</tt></p>

<pre>constexpr bool ends_with(const charT* x) const;
</pre>
<p>Effects: Equivalent to: <tt>return ends_with(basic_string_view(x));</tt></p>

<h2><a name="references">7. References</a></h2><a name="references">
<p></p></a><ol><a name="references">
  </a><li><a name="references">
    </a><a name="ref1"></a>The Python Standard Library. Built-in Types,
    <a href="https://docs.python.org/3.6/library/stdtypes.html#text-sequence-type-str">
    https://docs.python.org/3.6/library/stdtypes.html#text-sequence-type-str</a>
  </li>
  <li>
    <a name="ref2"></a>Java™ Platform, Standard Edition 7 API Specification. Class String,
    <a href="https://docs.oracle.com/javase/7/docs/api/java/lang/String.html">
    https://docs.oracle.com/javase/7/docs/api/java/lang/String.html</a>
  </li>
  <li>
    <a name="ref3"></a>Qt Documentation. QString Class.
    <a href="http://doc.qt.io/qt-5/qstring.html">
    http://doc.qt.io/qt-5/qstring.html</a>
  </li>
  <li>
    <a name="ref4"></a>string_view: a non-owning reference to a string, revision 3,
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3609.html">
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3609.html</a>
  </li>
  <li>
    <a name="ref5"></a>Integrating std::string_view and std::string,
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0254r1.pdf">
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0254r1.pdf</a>
  </li>
</ol><p></p>


</body></html>