﻿<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>N3180 - More on noexcept for the Strings Library</title>

  <style type="text/css">
    p {text-align:justify}
    li {text-align:justify}
    ins {background-color:#A0FFA0}
    del {background-color:#FF6666}
    
    tr.TITLE_ROW {text-align: center; font-weight: bold}
    tr.DELETED {background: #FF6666; text-decoration: line-through}
    tr.INSERTED {background: #FFFF99}
  </style>

  </head>

  <body>
<address>Document number: N3180=10-0170<br/>
  Date: 2010-11-11<br/>
  J. Daniel Garcia<br/>
  Project: Programming Language C++, Library Working Group<br />
  Reply To: <a href="mailto:josedaniel.garcia@uc3m.es">josedaniel.garcia@uc3m.es</a>
</address>
 
<hr/>

<h1>N3180 - More on noexcept for the Strings Library</h1>

<p>This paper studies possible changes to the Strings Library to make broad use of noexcept. The paper 
addresses National Body comments CH 16 and GB 60.</p>

<p>
Changes in this paper are <b>restricted to chapter 21</b> (strings library).
</p>

<p>
All changes in this paper are relative to N3126
</p>

<h2>Discussion</h2>

In general, this paper takes a aggresive path for noexceptifying the string library. The basic assumption is
that any <em>char traits</em> must offer <tt>noexcept</tt> operations. This basic assumption may be arguable
but I am not aware of any string implementation where operations defined in char traits may throw.

<h3>Char traits</h3>

Operations at character traits have been specified as non-throwing.

Those operations have been made noexcept in every library provided instantiation.

<h3>String classes</h3>

<p>
In general, many operations of string classes may throw. One exception are member functions <tt>erase()</tt> and
<tt>pop_back</tt> which cannot throw (21.4.1/3). However, 21.4.6.5/2 specifies ther first version<tt>erase()</tt>
to throw. 
</p>

<p>
Move constructor has been made throwing as it can only throw if moving an allocator may throw, but allocators do not throw on move.
</p>

<p>
Iterator support member functions return iterators to the beginning or the end of the string. The only situation
in which those members could throw is returning the iterator. However, those <em>implementation-defined</em>
iterator types are cross-referenced to clause 23.2 and 23.2.1/11 states that 
<em>no copy constructor or assignment operator of a returned iterator throws an exception</em>. Thus,
those member functions have been made <tt>noexcept</tt>.
</p>

<p>
Member function <tt>length()</tt> is specified in terms of the non-throwing <tt>size()</tt>. Thus, it has
been made <tt>noexcept</tt>. Besides, <tt>max_size</tt> has also been made <tt>noexcept</tt>, as this value
can be computed without the need of any throwing operation. This was also the case of <tt>capacity()</tt>.
However, member function <tt>shrink_to_fit()</tt> cannot be made <tt>noexcept</tt> as it may need to
reallocate some memory which is potentially throwing.
</p>

<p>
Member function <tt>clear()</tt> behaves as a call to <tt>erase(begin(), end())</tt> that cannot throw by
definition of <tt>erase()</tt>.
</p>

<p>
Member function <tt>empty()</tt> cannot throw because is specified in terms of non-throwing <tt>size()</tt>.
</p>

<p>
Member functions <tt>front()</tt> and <tt>back()</tt> cannot throw. They are specified in terms of non-throwing
operator <tt>[]</tt> accessing to a knowing position.
</p>

<p>
Member function <tt>pop_back()</tt> is specified in terms of <tt>erase()</tt> on an existing position and length.
That makes impossible to throw, independently of wether <tt>erase()</tt> is non-throwing or not (see open points).
</p>

<p>
Member function <tt>swap()</tt> is made <tt>noexcept</tt> by paper N3195. However, it is made <tt>noexcept</tt> here
to guarantee consistency.
</p>

<p>
Member function <tt>get_allocator</tt> may be made <tt>noexcept</tt> because any allocator satisfying allocator
requirements cannot throw when copying and/or moving.
</p>

<p>Several member functions for finding follow a common pattern. The basic version is based on <tt>traits::eq()</tt>
(and is consquently <tt>noexcept</tt>) and the rest of versions are based on the basic version. This
has been found for member functions <tt>find()</tt>, <tt>rfind()</tt>, <tt>find_first_of()</tt>, <tt>find_last_of</tt>,
<tt>find_first_not_of</tt> and <tt>find_last_not_of</tt>. Thus, all of them have been made <tt>noexcept</tt>.
</p>

<p>Member function <tt>compare()</tt> has several versions. Comparison between to <tt>basic_string</tt>'s can be
made non-throwing as it only coudl throw if the corresponding <tt>traits::compare()</tt> threw, which is not possible.
Besides, the version taking a <tt>charT*</tt> as an argument (21.4.7.9/5) could be made conditionally 
<tt>noexcept</tt> with a small change. Currently its effects are specified as a call to 
<tt>compare(basic_string(s))</tt>. Such a call is potentially throwing if allocation is performed. I <u>propose
	that the effects are specified in terms of</u> <em>as-if</em> to allow a <tt>noexcept</tt> specification.
</p>

<p>
Non-member comparsion operators may be expressed in terms of member function <tt>compare()</tt>. This has been
very easily done for <tt>==</tt> and <tt>!=</tt>. However, for the rest of comparison operators <u>some <em>Returns:</em>
	clauses have been re-worked</u> to make clear that they can be expressed without the need of temporals 
that could cause allocation exceptions.
</p>

<p>
Non-member function <tt>swap()</tt> has been made noexcept as it is based on non-throwing member <tt>swap()</tt>.
</p>

<h2>Acknowledgments</h2>

Daniel Kr&uuml;gler reviewed a preliminary version of this paper providing very useful suggestions and hints.

<h1>Proposed Wording</h1>

<h2>21.2.3.1 struct char_traits&lt;char&gt; [char.traits.specializations.char]</h2>

Before p. 1
<pre>
namespace std {
  template&lt;&gt; struct char_traits&lt;char&gt; {
    typedef char char_type;
    typedef int int_type;
    typedef streamoff off_type;
    typedef streampos pos_type;
    typedef mbstate_t state_type;

    static void assign(char_type&amp; c1, const char_type&amp; c2)<ins> noexcept</ins>;
    static constexpr bool eq(char_type c1, char_type c2)<ins> noexcept</ins>;
    static constexpr bool lt(char_type c1, char_type c2)<ins> noexcept</ins>;

    static int compare(const char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static size_t length(const char_type* s)<ins> noexcept</ins>;
    static const char_type* find(const char_type* s, size_t n,
                                 const char_type&amp; a)<ins> noexcept</ins>;
    static char_type* move(char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static char_type* copy(char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static char_type* assign(char_type* s, size_t n, char_type a)<ins> noexcept</ins>;

    static constexpr int_type not_eof(int_type c)<ins> noexcept</ins>;
    static constexpr char_type to_char_type(int_type c)<ins> noexcept</ins>;
    static constexpr int_type to_int_type(char_type c)<ins> noexcept</ins>;
    static constexpr bool eq_int_type(int_type c1, int_type c2)<ins> noexcept</ins>;
    static constexpr int_type eof()<ins> noexcept</ins>;
  };
}
</pre>

<h2>21.2.3.2 struct char_traits&lt;char16_t&gt; [char.traits.specializations.char16_t]</h2>

Before p. 1
<pre>
namespace std {
  template&lt;&gt; struct char_traits&lt;char16_t&gt; {
    typedef char16_t char_type;
    typedef uint_least16_t int_type;
    typedef streamoff off_type;
    typedef u16streampos pos_type;
    typedef mbstate_t state_type;

    static void assign(char_type&amp; c1, const char_type&amp; c2)<ins> noexcept</ins>;
    static constexpr bool eq(char_type c1, char_type c2)<ins> noexcept</ins>;
    static constexpr bool lt(char_type c1, char_type c2)<ins> noexcept</ins>;

    static int compare(const char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static size_t length(const char_type* s)<ins> noexcept</ins>;
    static const char_type* find(const char_type* s, size_t n,
                                 const char_type&amp; a)<ins> noexcept</ins>;
    static char_type* move(char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static char_type* copy(char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static char_type* assign(char_type* s, size_t n, char_type a)<ins> noexcept</ins>;
    
    static constexpr int_type not_eof(int_type c)<ins> noexcept</ins>;
    static constexpr char_type to_char_type(int_type c)<ins> noexcept</ins>;
    static constexpr int_type to_int_type(char_type c)<ins> noexcept</ins>;
    static constexpr bool eq_int_type(int_type c1, int_type c2)<ins> noexcept</ins>;
    static constexpr int_type eof()<ins> noexcept</ins>;
  };
}
</pre>

<h2>21.2.3.3 struct char_traits&lt;char32_t&gt; [char.traits.specializations.char32_t]</h2>

Before p. 1
<pre>
namespace std {
  template&lt;&gt; struct char_traits&lt;char32_t&gt; {
    typedef char32_t char_type;
    typedef uint_least32_t int_type;
    typedef streamoff off_type;
    typedef u32streampos pos_type;
    typedef mbstate_t state_type;

    static void assign(char_type&amp; c1, const char_type&amp; c2)<ins> noexcept</ins>;
    static constexpr bool eq(char_type c1, char_type c2)<ins> noexcept</ins>;
    static constexpr bool lt(char_type c1, char_type c2)<ins> noexcept</ins>;
    static int compare(const char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static size_t length(const char_type* s)<ins> noexcept</ins>;
    static const char_type* find(const char_type* s, size_t n,
                                 const char_type&amp; a)<ins> noexcept</ins>;
    static char_type* move(char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static char_type* copy(char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static char_type* assign(char_type* s, size_t n, char_type a)<ins> noexcept</ins>;

    static constexpr int_type not_eof(int_type c)<ins> noexcept</ins>;
    static constexpr char_type to_char_type(int_type c)<ins> noexcept</ins>;
    static constexpr int_type to_int_type(char_type c)<ins> noexcept</ins>;
    static constexpr bool eq_int_type(int_type c1, int_type c2)<ins> noexcept</ins>;
    static constexpr int_type eof()<ins> noexcept</ins>;
  };
}
</pre>

<h2>21.2.3.4 struct char_traits<wchar_t> [char.traits.specializations.wchar.t]</h2>

Before p. 1
<pre>
namespace std {
  template&lt;&gt; struct char_traits&lt;wchar_t&gt; {
    typedef wchar_t char_type;
    typedef wint_t int_type;
    typedef streamoff off_type;
    typedef wstreampos pos_type;
    typedef mbstate_t state_type;

    static void assign(char_type&amp; c1, const char_type&amp; c2)<ins> noexcept</ins>;
    static constexpr bool eq(char_type c1, char_type c2)<ins> noexcept</ins>;
    static constexpr bool lt(char_type c1, char_type c2)<ins> noexcept</ins>;

    static int compare(const char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static size_t length(const char_type* s)<ins> noexcept</ins>;
    static const char_type* find(const char_type* s, size_t n,
                                 const char_type&amp; a)<ins> noexcept</ins>;
    static char_type* move(char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static char_type* copy(char_type* s1, const char_type* s2, size_t n)<ins> noexcept</ins>;
    static char_type* assign(char_type* s, size_t n, char_type a)<ins> noexcept</ins>;
    
    static constexpr int_type not_eof(int_type c)<ins> noexcept</ins>;
    static constexpr char_type to_char_type(int_type c)<ins> noexcept</ins>;
    static constexpr int_type to_int_type(char_type c)<ins> noexcept</ins>;
    static constexpr bool eq_int_type(int_type c1, int_type c2)<ins> noexcept</ins>;
    static constexpr int_type eof()<ins> noexcept</ins>;
  };
}
</pre>

<h2>21.3 String classes [string.classes]</h2>

After p. 1
<pre>
namespace std {
...
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator==(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
                    const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcep</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator==(const charT* lhs,
		    const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator==(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		    const charT* rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator!=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		    const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator!=(const charT* lhs,
		    const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator!=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
                    const charT* rhs)<ins> noexcept</ins>;

  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&lt; (const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		       const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&lt; (const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		       const charT* rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&lt; (const charT* lhs,
		       const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&gt; (const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		       const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&gt; (const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		       const charT* rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&gt; (const charT* lhs,
                       const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&lt;=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		       const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&lt;=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		       const charT* rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&lt;=(const charT* lhs,
		       const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&gt;=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		       const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&gt;=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		       const charT* rhs)<ins> noexcept</ins>;
  template&lt;class charT, class traits, class Allocator&gt;
    bool operator&gt;=(const charT* lhs,
                       const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
  // 21.4.8.8: swap
  template&lt;class charT, class traits, class Allocator&gt;
    void swap(basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
	      basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;

...
}
</pre>

<h2>21.4 Class template basic_string [basic.string]</h2>

After p. 5
<pre>
namespace std {
  template&lt;class charT, class traits = char_traits&lt;charT&gt;,
              class Allocator = allocator&lt;charT&gt; &gt;
  class basic_string {
  public:
...
    // 21.4.2 construct/copy/destroy:
    basic_string(basic_string&amp;&amp; str)<ins> noexcept</ins>;
...
    // 21.4.3 iterators:
    iterator begin()<ins> noexcept</ins>;
    const_iterator begin() const<ins> noexcept</ins>;
    iterator end()<ins> noexcept</ins>;

    const_iterator end() const<ins> noexcept</ins>;
    reverse_iterator rbegin()<ins> noexcept</ins>;
    const_reverse_iterator rbegin() const<ins> noexcept</ins>;

    reverse_iterator rend()<ins> noexcept</ins>;
    const_reverse_iterator rend() const<ins> noexcept</ins>;
    const_iterator cbegin() const<ins> noexcept</ins>;

    const_iterator cend() const<ins> noexcept</ins>;
    const_reverse_iterator crbegin() const<ins> noexcept</ins>;
    const_reverse_iterator crend() const<ins> noexcept</ins>;

    // 21.4.4 capacity:
...
    size_type length() const<ins> noexcept</ins>;
    size_type max_size() const<ins> noexcept</ins>;
...
    size_type capacity() const<ins> noexcept</ins>;
...
    void clear()<ins> noexcept</ins>;
    bool empty() const<ins> noexcept</ins>;

    // 21.4.5 element access:
...
    const charT&amp; front() const<ins> noexcept</ins>;
    charT&amp; front()<ins> noexcept</ins>;
    const charT&amp; back() const<ins> noexcept</ins>;
    charT&amp; back()<ins> noexcept</ins>;

    // 21.4.6 modifiers:
...
    void pop_back()<ins> noexcept</ins>;
...
    void swap(basic_string&amp; str)<ins> noexcept</ins>;

    // 21.4.7 string operations:
...
    allocator_type get_allocator() const<ins> noexcept</ins>;

    size_type find (const basic_string&amp; str, size_type pos = 0) const<ins> noexcept</ins>;
    size_type find (const charT* s, size_type pos, size_type n) const<ins> noexcept</ins>;
    size_type find (const charT* s, size_type pos = 0) const<ins> noexcept</ins>;
    size_type find (charT c, size_type pos = 0) const<ins> noexcept</ins>;
    size_type rfind(const basic_string&amp; str, size_type pos = npos) const<ins> noexcept</ins>;
    size_type rfind(const charT* s, size_type pos, size_type n) const<ins> noexcept</ins>;
    size_type rfind(const charT* s, size_type pos = npos) const<ins> noexcept</ins>;
    size_type rfind(charT c, size_type pos = npos) const<ins> noexcept</ins>;

    size_type find_first_of(const basic_string&amp; str,
			    size_type pos = 0) const<ins> noexcept</ins>;
    size_type find_first_of(const charT* s,
			    size_type pos, size_type n) const<ins> noexcept</ins>;
    size_type find_first_of(const charT* s, size_type pos = 0) const<ins> noexcept</ins>;
    size_type find_first_of(charT c, size_type pos = 0) const<ins> noexcept</ins>;
    size_type find_last_of (const basic_string&amp; str,
			    size_type pos = npos) const<ins> noexcept</ins>;
    size_type find_last_of (const charT* s,
			    size_type pos, size_type n) const<ins> noexcept</ins>;
    size_type find_last_of (const charT* s, size_type pos = npos) const<ins> noexcept</ins>;
    size_type find_last_of (charT c, size_type pos = npos) const<ins> noexcept</ins>;

    size_type find_first_not_of(const basic_string&amp; str,
				size_type pos = 0) const<ins> noexcept</ins>;
    size_type find_first_not_of(const charT* s, size_type pos,
				size_type n) const<ins> noexcept</ins>;
    size_type find_first_not_of(const charT* s, size_type pos = 0) const<ins> noexcept</ins>;
    size_type find_first_not_of(charT c, size_type pos = 0) const<ins> noexcept</ins>;
    size_type find_last_not_of (const basic_string&amp; str,
				size_type pos = npos) const<ins> noexcept</ins>;
    size_type find_last_not_of (const charT* s, size_type pos,
				size_type n) const<ins> noexcept</ins>;
    size_type find_last_not_of (const charT* s,
				size_type pos = npos) const<ins> noexcept</ins>;
    size_type find_last_not_of (charT c, size_type pos = npos) const<ins> noexcept</ins>;
...
    int compare(const basic_string&amp; str) const<ins> noexcept</ins>; 
...
    int compare(const charT* s) const<ins> noexcept</ins>;
  };
}
</pre>

<h2>21.4.1 basic_string general requirements [string.require]</h2>

Modify p. 3
<p>No erase() or pop_back() member function shall throw any exceptions.</p>

<h2>21.4.2 basic_string constructors and assigment operators [string.cons]</h2>

After p. 1
<pre>
basic_string(const basic_string<charT,traits,Allocator>&amp; str);
basic_string(basic_string<charT,traits,Allocator>&amp;&amp; str)<ins>noexcept</ins>;
</pre>

<h2>21.4.3 basic_string iterator support [string.iterators]</h2>

Before p. 1
<pre>
iterator begin()<ins> noexcept</ins>;
const_iterator begin() const<ins> noexcept</ins>;
const_iterator cbegin() const<ins> noexcept</ins>;
</pre>

Before p. 2
<pre>
iterator end()<ins> noexcept</ins>;
const_iterator end() const<ins> noexcept</ins>;
const_iterator cend() const<ins> noexcept</ins>;
</pre>

Before p. 3
<pre>
reverse_iterator rbegin()<ins> noexcept</ins>;
const_reverse_iterator rbegin() const<ins> noexcept</ins>;
const_reverse_iterator crbegin() const<ins> noexcept</ins>;
</pre>

Before p. 4
<pre>
reverse_iterator rend()<ins> noexcept</ins>;
const_reverse_iterator rend() const<ins> noexcept</ins>;
const_reverse_iterator crend() const<ins> noexcept</ins>;
</pre>

<h2>21.4.4 basic_string capacity [string.capacity]</h2>

After p. 3
<pre>size_type length() const<ins> noexcept</ins>;</pre>

After p. 4
<pre>size_type max_size() const<ins> noexcept</ins>;</pre>

After p. 10
<pre>size_type capacity() const<ins> noexcept</ins>;</pre>

After p. 15
<pre>void clear()<ins> noexcept</ins>;</pre>

After p. 16
<pre>bool empty() const<ins> noexcept</ins>;</pre>

<h2>21.4.5 basic_string element access [string.access]</h2>

After p. 7
<pre>
const charT&amp; front() const<ins> noexcept</ins>;
charT&amp; front()<ins> noexcept</ins>;
</pre>

After p. 9
<pre>
const charT&amp; back() const<ins> noexcept</ins>;
charT&amp; back()<ins> noexcept</ins>;
</pre>

<h2>21.4.6.5 basic_string::erase [string::erase]</h2>

After p. 10
<pre>
void pop_back()<ins> noexcept</ins>;
</pre>

<h2>21.4.6.8 basic_string::swap [string::swap]</h2>

Before p. 1
<pre>void swap(basic_string<charT,traits,Allocator>&amp; s)<ins> noexcept</ins>;</pre>
<p><del>1 Throws: Nothing.</del></p>

<h2>21.4.7.1 basic_string accessors [string.accessors]</h2>

After p. 4
<pre>
allocator_type get_allocator() const<ins> noexcept</em>;
</pre>

<h2>21.4.7.2 basic_string::find [string::find]</h2>

Before p. 1
<pre>
size_type find(const basic_string&amp; str,
               size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 3
<pre>
size_type find(const charT* s, size_type pos, size_type n) const<ins> noexcept</ins>;
</pre>

After p. 4
<pre>
size_type find(const charT* s, size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 6
<pre>
size_type find(charT c, size_type pos = 0) const<ins> noexcept</ins>;
</pre>


<h2>21.4.7.3 basic_string::rfind [string::rfind]</h2>

Before p. 1
<pre>
size_type rfind(const basic_string&amp; str,
               size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 3
<pre>
size_type rfind(const charT* s, size_type pos, size_type n) const<ins> noexcept</ins>;
</pre>

After p. 4
<pre>
size_type rfind(const charT* s, size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 6
<pre>
size_type rfind(charT c, size_type pos = 0) const<ins> noexcept</ins>;
</pre>

<h2>21.4.7.4 basic_string::find_first_of [string::find.first.of]</h2>

Before p. 1
<pre>
size_type
  find_first_of(const basic_string&amp; str,
		size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 3
<pre>
size_type
  find_first_of(const charT* s, size_type pos, size_type n) const<ins> noexcept</ins>;
</pre>

After p. 4
<pre>
size_type find_first_of(const charT* s, size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 6
<pre>
size_type find_first_of(charT c, size_type pos = 0) const<ins> noexcept</ins>;
</pre>

<h2>21.4.7.5 basic_string::find_last_of [string::find.last.of]</h2>

Before p. 1
<pre>
size_type
  find_last_of(const basic_string&amp; str,
		size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 3
<pre>
size_type
  find_last_of(const charT* s, size_type pos, size_type n) const<ins> noexcept</ins>;
</pre>

After p. 4
<pre>
size_type find_last_of(const charT* s, size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 6
<pre>
size_type find_last_of(charT c, size_type pos = 0) const<ins> noexcept</ins>;
</pre>

<h2>21.4.7.6 basic_string::find_first_not_of [string::find.first.not.of]</h2>

Before p. 1
<pre>
size_type
  find_first_not_of(const basic_string&amp; str,
		    size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 3
<pre>
size_type
  find_first_not_of(const charT* s, size_type pos, size_type n) const<ins> noexcept</ins>;
</pre>

After p. 4
<pre>
size_type find_first_not_of(const charT* s, size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 6
<pre>
size_type find_first_not_of(charT c, size_type pos = 0) const<ins> noexcept</ins>;
</pre>

<h2>21.4.7.7 basic_string::find_last_not_of [string::find.last.not.of]</h2>

Before p. 1
<pre>
size_type
  find_last_not_of(const basic_string&amp; str,
		size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 3
<pre>
size_type
  find_last_not_of(const charT* s, size_type pos, size_type n) const<ins> noexcept</ins>;
</pre>

After p. 4
<pre>
size_type find_last_not_of(const charT* s, size_type pos = 0) const<ins> noexcept</ins>;
</pre>

After p. 6
<pre>
size_type find_last_not_of(charT c, size_type pos = 0) const<ins> noexcept</ins>;
</pre>

<h2>21.4.7.9 basic_string::compare [string::compare]</h2>

Before p. 1
<pre>
int compare(const basic_string&amp; str) const<ins> noexcept</ins>;
</pre>

After p. 4
<pre>
int compare(const charT *s) const<ins> noexcept</ins>;
</pre>
<p>5 <em>Returns</em>: <ins>Equivalent to </ins><tt>compare(basic_string(s))</tt>.

<h2>21.4.8.2 operator== [string::operator==]</h2>

Before p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator==(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		  const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>

After p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator==(const charT* lhs,
                  const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>

After p. 2
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator==(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
                  const charT* rhs)<ins> noexcept</ins>;
</pre>

<h2>21.4.8.3 operator!= [string::op!=]</h2>

Before p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator!=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
                  const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>

After p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator!=(const charT* lhs,
		  const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>

After p. 2
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator!=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
                  const charT* rhs)<ins> noexcept</ins>;
</pre>

<h2>21.4.8.4 operator&lt; [string::op&lt;]</h2>

Before p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&lt; (const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
                     const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>

After p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&lt; (const charT* lhs,
                     const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>
<p>2 <em>Returns</em>: <del><tt>basic_string&lt;charT,traits,Allocator&gt;(lhs) &lt; rhs</tt></del>
<ins><tt>rhs.compare(lhs) &gt; 0</tt></ins>.</p>

After p. 2
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&lt; (const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
                     const charT* rhs)<ins> noexcept</ins>;
</pre>
<p>3 <em>Returns</em>: <del><tt>lhs &lt; basic_string&lt;charT,traits,Allocator&gt;(rhs)</tt></del>
<ins><tt>lhs.compare(rhs) &lt; 0</tt></ins>.</p>

<h2>21.4.8.5 operator&gt; [string::op&gt;]</h2>

Before p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&gt; (const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		     const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>

After p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&gt; (const charT* lhs,
                     const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>
<p>2 <em>Returns</em>: <del><tt>basic_string&lt;charT,traits,Allocator&gt;(lhs) &gt; rhs</tt></del>
<ins><tt>rhs.compare(lhs) &lt; 0</tt></ins>.</p>

After p. 2
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&gt; (const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
		     const charT* rhs)<ins> noexcept</ins>;
</pre>
<p>3 <em>Returns</em>: <del><tt>lhs &gt; basic_string&lt;charT,traits,Allocator&gt;(rhs)</tt></del>
<ins><tt>lhs.compare(rhs) &gt; 0</tt></ins>.</p>

<h2>21.4.8.6 operator&lt;= [string::op&lt;=]</h2>

Before p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&lt;=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
                     const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>

After p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&lt;=(const charT* lhs,
                     const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>
<p>2 <em>Returns</em>: <del><tt>basic_string&lt;charT,traits,Allocator&gt;(lhs) &lt;= rhs</tt></del>
<ins><tt>rhs.compare(lhs) &gt;= 0</tt></ins>.</p>

After p. 2
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&lt;=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
                     const charT* rhs)<ins> noexcept</ins>;
</pre>
<p>3 <em>Returns</em>: <del><tt>lhs &lt;= basic_string&lt;charT,traits,Allocator&gt;(rhs)</tt></del>
<ins><tt>lhs.compare(rhs) &lt;= 0</tt></ins>.</p>

<h2>21.4.8.7 operator&gt;= [string::op&gt;=]</h2>

Before p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&gt;=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
                     const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>

After p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&gt;=(const charT* lhs,
                     const basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>
<p>2 <em>Returns</em>: <del><tt>basic_string&lt;charT,traits,Allocator&gt;(lhs) &gt;= rhs</tt></del>
<ins><tt>rhs.compare(lhs) &lt;= 0</tt></ins>.</p>

After p. 2
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  bool operator&gt;=(const basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
                     const charT* rhs)<ins> noexcept</ins>;
</pre>
<p>3 <em>Returns</em>: <del><tt>lhs &gt;= basic_string&lt;charT,traits,Allocator&gt;(rhs)</tt></del>
<ins><tt>lhs.compare(rhs) &gt;= 0</tt></ins>.</p>

<h2>21.4.8.8 swap [string.special]</h2>

Before p. 1
<pre>
template&lt;class charT, class traits, class Allocator&gt;
  void swap(basic_string&lt;charT,traits,Allocator&gt;&amp; lhs,
            basic_string&lt;charT,traits,Allocator&gt;&amp; rhs)<ins> noexcept</ins>;
</pre>
</body>
</html>
