[string.nonmembers]

# 27 Strings library [[strings]](./#strings)

## 27.4 String classes [[string.classes]](string.classes#string.nonmembers)

### 27.4.4 Non-member functions [string.nonmembers]

#### [27.4.4.1](#string.op.plus) operator+ [[string.op.plus]](string.op.plus)

[ð](#lib:operator+,basic_string)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const basic_string<charT, traits, Allocator>& lhs,
              const basic_string<charT, traits, Allocator>& rhs);
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const basic_string<charT, traits, Allocator>& lhs, const charT* rhs);
`

[1](#string.op.plus-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4719)

*Effects*: Equivalent to:basic_string<charT, traits, Allocator> r = lhs;
r.append(rhs);return r;

[ð](#lib:operator+,basic_string_)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(basic_string<charT, traits, Allocator>&& lhs,
              const basic_string<charT, traits, Allocator>& rhs);
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(basic_string<charT, traits, Allocator>&& lhs, const charT* rhs);
`

[2](#string.op.plus-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4741)

*Effects*: Equivalent to:lhs.append(rhs);return std::move(lhs);

[ð](#lib:operator+,basic_string__)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(basic_string<charT, traits, Allocator>&& lhs,
              basic_string<charT, traits, Allocator>&& rhs);
`

[3](#string.op.plus-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4759)

*Effects*: Equivalent to:lhs.append(rhs);return std::move(lhs); except that both lhs and rhs are left in valid but unspecified states[.](#string.op.plus-3.sentence-1)

[*Note [1](#string.op.plus-note-1)*:

If lhs and rhs have equal allocators,
the implementation can move from either[.](#string.op.plus-3.sentence-2)

â *end note*]

[ð](#lib:operator+,basic_string___)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const basic_string<charT, traits, Allocator>& lhs,
              basic_string<charT, traits, Allocator>&& rhs);
template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const charT* lhs, basic_string<charT, traits, Allocator>&& rhs);
`

[4](#string.op.plus-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4786)

*Effects*: Equivalent to:rhs.insert(0, lhs);return std::move(rhs);

[ð](#lib:operator+,basic_string____)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const charT* lhs, const basic_string<charT, traits, Allocator>& rhs);
`

[5](#string.op.plus-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4803)

*Effects*: Equivalent to:basic_string<charT, traits, Allocator> r = rhs;
r.insert(0, lhs);return r;

[ð](#lib:operator+,basic_string_____)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(charT lhs, const basic_string<charT, traits, Allocator>& rhs);
`

[6](#string.op.plus-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4821)

*Effects*: Equivalent to:basic_string<charT, traits, Allocator> r = rhs;
r.insert(r.begin(), lhs);return r;

[ð](#lib:operator+,basic_string______)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(charT lhs, basic_string<charT, traits, Allocator>&& rhs);
`

[7](#string.op.plus-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4839)

*Effects*: Equivalent to:rhs.insert(rhs.begin(), lhs);return std::move(rhs);

[ð](#lib:operator+,basic_string_______)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs);
`

[8](#string.op.plus-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4856)

*Effects*: Equivalent to:basic_string<charT, traits, Allocator> r = lhs;
r.push_back(rhs);return r;

[ð](#lib:operator+,basic_string________)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(basic_string<charT, traits, Allocator>&& lhs, charT rhs);
`

[9](#string.op.plus-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4874)

*Effects*: Equivalent to:lhs.push_back(rhs);return std::move(lhs);

[ð](#lib:operator+,basic_string_________)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(const basic_string<charT, traits, Allocator>& lhs,
              type_identity_t<basic_string_view<charT, traits>> rhs);
`

[10](#string.op.plus-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4892)

Equivalent to:basic_string<charT, traits, Allocator> r = lhs;
r.append(rhs);return r;

[ð](#lib:operator+,basic_string__________)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(basic_string<charT, traits, Allocator>&& lhs,
              type_identity_t<basic_string_view<charT, traits>> rhs);
`

[11](#string.op.plus-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4910)

Equivalent to:lhs.append(rhs);return std::move(lhs);

[ð](#lib:operator+,basic_string___________)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
              const basic_string<charT, traits, Allocator>& rhs);
`

[12](#string.op.plus-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4927)

Equivalent to:basic_string<charT, traits, Allocator> r = rhs;
r.insert(0, lhs);return r;

[ð](#lib:operator+,basic_string____________)

`template<class charT, class traits, class Allocator>
  constexpr basic_string<charT, traits, Allocator>
    operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
              basic_string<charT, traits, Allocator>&& rhs);
`

[13](#string.op.plus-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4945)

Equivalent to:rhs.insert(0, lhs);return std::move(rhs);

[14](#string.op.plus-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4953)

[*Note [2](#string.op.plus-note-2)*:

Using a specialization of type_identity_t as a parameter type ensures
that an object of type basic_string<charT, traits, Allocator> can be concatenated with an object of a type T having an implicit conversion tobasic_string_view<charT, traits> ([[over.match.oper]](over.match.oper "12.2.2.3 Operators in expressions"))[.](#string.op.plus-14.sentence-1)

â *end note*]

#### [27.4.4.2](#string.cmp) Non-member comparison operator functions [[string.cmp]](string.cmp)

[ð](#string.cmp-itemdecl:1)

`template<class charT, class traits, class Allocator>
  constexpr bool
    operator==(const basic_string<charT, traits, Allocator>& lhs,
               const basic_string<charT, traits, Allocator>& rhs) noexcept;
template<class charT, class traits, class Allocator>
  constexpr bool operator==(const basic_string<charT, traits, Allocator>& lhs,
                            const charT* rhs);

template<class charT, class traits, class Allocator>
  constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs,
                                  const basic_string<charT, traits, Allocator>& rhs) noexcept;
template<class charT, class traits, class Allocator>
  constexpr see below operator<=>(const basic_string<charT, traits, Allocator>& lhs,
                                  const charT* rhs);
`

[1](#string.cmp-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L4980)

*Effects*: Let *op* be the operator[.](#string.cmp-1.sentence-1)

Equivalent to:return basic_string_view<charT, traits>(lhs) *op* basic_string_view<charT, traits>(rhs);

#### [27.4.4.3](#string.special) swap [[string.special]](string.special)

[ð](#lib:swap,basic_string)

`template<class charT, class traits, class Allocator>
  constexpr void
    swap(basic_string<charT, traits, Allocator>& lhs,
         basic_string<charT, traits, Allocator>& rhs)
      noexcept(noexcept(lhs.swap(rhs)));
`

[1](#string.special-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5001)

*Effects*: Equivalent to lhs.swap(rhs)[.](#string.special-1.sentence-1)

#### [27.4.4.4](#string.io) Inserters and extractors [[string.io]](string.io)

[ð](#lib:operator%3e%3e,basic_string)

`template<class charT, class traits, class Allocator>
  basic_istream<charT, traits>&
    operator>>(basic_istream<charT, traits>& is, basic_string<charT, traits, Allocator>& str);
`

[1](#string.io-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5016)

*Effects*: Behaves as a formatted input function ([[istream.formatted.reqmts]](istream.formatted.reqmts "31.7.5.3.1 Common requirements"))[.](#string.io-1.sentence-1)

After constructing a sentry object,
if the sentry object returns true when converted to a value of type bool,
calls str.erase() and then extracts characters from is and appends them
to str as if by callingstr.append(1, c)[.](#string.io-1.sentence-2)

Ifis.width() is greater than zero, the maximum
number n of characters appended isis.width();
otherwise n isstr.max_size()[.](#string.io-1.sentence-3)

Characters are extracted and appended until any of the following
occurs:

- [(1.1)](#string.io-1.1)

*n* characters are stored;

- [(1.2)](#string.io-1.2)

end-of-file occurs on the input sequence;

- [(1.3)](#string.io-1.3)

isspace(c, is.getloc()) is true for the next available input character*c*[.](#string.io-1.sentence-4)

[2](#string.io-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5047)

After the last character (if any) is extracted,is.width(0) is called and thesentry object is destroyed[.](#string.io-2.sentence-1)

[3](#string.io-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5054)

If the function extracts no characters,ios_base​::​failbit is set in the input function's local error state
before setstate is called[.](#string.io-3.sentence-1)

[4](#string.io-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5059)

*Returns*: is[.](#string.io-4.sentence-1)

[ð](#lib:operator%3c%3c,basic_string)

`template<class charT, class traits, class Allocator>
  basic_ostream<charT, traits>&
    operator<<(basic_ostream<charT, traits>& os,
               const basic_string<charT, traits, Allocator>& str);
`

[5](#string.io-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5073)

*Effects*: Equivalent to: return os << basic_string_view<charT, traits>(str);

[ð](#lib:getline,basic_string)

`template<class charT, class traits, class Allocator>
  basic_istream<charT, traits>&
    getline(basic_istream<charT, traits>& is,
            basic_string<charT, traits, Allocator>& str,
            charT delim);
template<class charT, class traits, class Allocator>
  basic_istream<charT, traits>&
    getline(basic_istream<charT, traits>&& is,
            basic_string<charT, traits, Allocator>& str,
            charT delim);
`

[6](#string.io-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5093)

*Effects*: Behaves as an unformatted input function ([[istream.unformatted]](istream.unformatted "31.7.5.4 Unformatted input functions")),
except that it does not affect the value returned by subsequent calls tobasic_istream<>​::​gcount()[.](#string.io-6.sentence-1)

After constructing a sentry object,
if the sentry object returns true when converted to a value of type bool,
calls str.erase() and then extracts characters from is and appends them
to str as if by callingstr.append(1, c) until any of the following occurs:

- [(6.1)](#string.io-6.1)

end-of-file occurs on the input sequence;

- [(6.2)](#string.io-6.2)

traits​::​eq(c, delim) for the next available input character*c* (in which case,*c* is extracted but not appended);

- [(6.3)](#string.io-6.3)

str.max_size() characters are stored
(in which case,ios_base​::​failbit is set in the input function's local error state)[.](#string.io-6.sentence-2)

[7](#string.io-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5123)

The conditions are tested in the order shown[.](#string.io-7.sentence-1)

In any case,
after the last character is extracted, thesentry object is destroyed[.](#string.io-7.sentence-2)

[8](#string.io-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5130)

If the function extracts no characters,ios_base​::​failbit is set in the input function's local error state
before setstate is called[.](#string.io-8.sentence-1)

[9](#string.io-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5135)

*Returns*: is[.](#string.io-9.sentence-1)

[ð](#lib:getline,basic_string_)

`template<class charT, class traits, class Allocator>
  basic_istream<charT, traits>&
    getline(basic_istream<charT, traits>& is,
            basic_string<charT, traits, Allocator>& str);
template<class charT, class traits, class Allocator>
  basic_istream<charT, traits>&
    getline(basic_istream<charT, traits>&& is,
            basic_string<charT, traits, Allocator>& str);
`

[10](#string.io-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5153)

*Returns*: getline(is, str, is.widen('\n'))[.](#string.io-10.sentence-1)

#### [27.4.4.5](#string.erasure) Erasure [[string.erasure]](string.erasure)

[ð](#lib:erase,basic_string)

`template<class charT, class traits, class Allocator, class U = charT>
  constexpr typename basic_string<charT, traits, Allocator>::size_type
    erase(basic_string<charT, traits, Allocator>& c, const U& value);
`

[1](#string.erasure-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5168)

*Effects*: Equivalent to:auto it = remove(c.begin(), c.end(), value);auto r = distance(it, c.end());
c.erase(it, c.end());return r;

[ð](#lib:erase_if,basic_string)

`template<class charT, class traits, class Allocator, class Predicate>
  constexpr typename basic_string<charT, traits, Allocator>::size_type
    erase_if(basic_string<charT, traits, Allocator>& c, Predicate pred);
`

[2](#string.erasure-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/strings.tex#L5187)

*Effects*: Equivalent to:auto it = remove_if(c.begin(), c.end(), pred);auto r = distance(it, c.end());
c.erase(it, c.end());return r;
