noexcept
Section: 27.4.3 [basic.string], 27.4.3.8.2 [string.find], 27.4.3.8.4 [string.compare] Status: Resolved Submitter: Jonathan Wakely Opened: 2016-12-05 Last modified: 2023-02-07
Priority: 2
View other active issues in [basic.string].
View all other issues in [basic.string].
View all issues with Resolved status.
Discussion:
Currently some overloads of basic_string::find
are noexcept
and some are not. Historically this
was because some were specified in terms of constructing a temporary basic_string
, which could throw. In
practice creating a temporary (and potentially allocating memory) is a silly implementation, and so they could be
noexcept
. In the C++17 draft most of them have been changed to create a temporary basic_string_view
instead, which can't throw anyway (P0254R2 made those changes).
find
, rfind
, find_first_of
, find_last_of
, find_first_not_of
and
find_last_not_of
overloads that are defined in terms of basic_string_view
should be noexcept
,
or "Throws: Nothing." for the ones with narrow contracts (even though those narrow contracts are not enforcable
or testable).
The remaining overloads that are still specified in terms of a temporary string could also be noexcept
. They
construct basic_string
of length one (which won't throw for an SSO implementation anyway), but can easily be
defined in terms of basic_string_view
instead.
There's one basic_string::compare
overload that is still defined in terms of a temporary basic_string
,
which should be basic_string_view
and so can also be noexcept
(the other compare
overloads can
throw out_of_range
).
[2016-12-15, Tim Song comments]
The following overloads invoking basic_string_view<charT>(s, n)
are implicitly narrow-contract
(the basic_string_view
constructor requires [s, s+n)
to be a valid range) and should be
"Throws: Nothing" rather than noexcept
:
size_type find(const charT* s, size_type pos, size_type n) const; size_type rfind(const charT* s, size_type pos, size_type n) const; size_type find_first_of(const charT* s, size_type pos, size_type n) const; size_type find_last_of(const charT* s, size_type pos, size_type n) const; size_type find_first_not_of(const charT* s, size_type pos, size_type n) const; size_type find_last_not_of(const charT* s, size_type pos, size_type n) const;
Similarly, the basic_string_view
constructor invoked by this overload of compare
requires
[s, s + traits::length(s))
to be a valid range, and so it should be "Throws: Nothing" rather
than noexcept
:
int compare(const charT* s) const;
[2017-01-27 Telecon]
Priority 2; Jonathan to provide updated wording
[2017-10-22, Marshall comments]
libc++ already has all of these member fns marked as noexcept
[2017-11 Albuquerque Saturday issues processing]
All the fns that take a const char *
are narrow contract, and so can't be noexcept. Should be "Throws: Nothing" instead. Alisdair to re-word.
[2018-08 mailing list discussion]
This will be resolved by Tim's string rework paper.
Resolved by the adoption of P1148 in San Diego.
Proposed resolution:
This wording is relative to N4618.
Change class template synopsis std::basic_string
, 27.4.3 [basic.string], as indicated:
size_type find (basic_string_view<charT, traits> sv, size_type pos = 0) const noexcept; size_type find (const basic_string& str, size_type pos = 0) const noexcept; size_type find (const charT* s, size_type pos, size_type n) const noexcept; size_type find (const charT* s, size_type pos = 0) const; size_type find (charT c, size_type pos = 0) const noexcept; size_type rfind(basic_string_view<charT, traits> sv, size_type pos = npos) const noexcept; size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; size_type rfind(const charT* s, size_type pos, size_type n) const noexcept; size_type rfind(const charT* s, size_type pos = npos) const; size_type rfind(charT c, size_type pos = npos) const noexcept; size_type find_first_of(basic_string_view<charT, traits> sv, size_type pos = 0) const noexcept; size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; size_type find_first_of(const charT* s, size_type pos, size_type n) const noexcept; size_type find_first_of(const charT* s, size_type pos = 0) const; size_type find_first_of(charT c, size_type pos = 0) const noexcept; size_type find_last_of (basic_string_view<charT, traits> sv, size_type pos = npos) const noexcept; size_type find_last_of (const basic_string& str, size_type pos = npos) const noexcept; size_type find_last_of (const charT* s, size_type pos, size_type n) const noexcept; size_type find_last_of (const charT* s, size_type pos = npos) const; size_type find_last_of (charT c, size_type pos = npos) const noexcept; size_type find_first_not_of(basic_string_view<charT, traits> sv, size_type pos = 0) const noexcept; size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept; size_type find_first_not_of(const charT* s, size_type pos, size_type n) const noexcept; size_type find_first_not_of(const charT* s, size_type pos = 0) const; size_type find_first_not_of(charT c, size_type pos = 0) const noexcept; size_type find_last_not_of (basic_string_view<charT, traits> sv, size_type pos = npos) const noexcept; size_type find_last_not_of (const basic_string& str, size_type pos = npos) const noexcept; size_type find_last_not_of (const charT* s, size_type pos, size_type n) const noexcept; size_type find_last_not_of (const charT* s, size_type pos = npos) const; size_type find_last_not_of (charT c, size_type pos = npos) const noexcept; basic_string substr(size_type pos = 0, size_type n = npos) const; int compare(basic_string_view<charT, traits> sv) const noexcept; int compare(size_type pos1, size_type n1, basic_string_view<charT, traits> sv) const; template<class T> int compare(size_type pos1, size_type n1, const T& t, size_type pos2, size_type n2 = npos) const; int compare(const basic_string& str) const noexcept; int compare(size_type pos1, size_type n1, const basic_string& str) const; int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2 = npos) const; int compare(const charT* s) const noexcept; int compare(size_type pos1, size_type n1, const charT* s) const; int compare(size_type pos1, size_type n1, const charT* s, size_type n2) const;
Change 27.4.3.8.2 [string.find] as indicated:
size_type find(const charT* s, size_type pos, size_type n) const noexcept;-5- Returns:
find(basic_string_view<charT, traits>(s, n), pos)
.size_type find(const charT* s, size_type pos = 0) const;-6- Requires:
-7- Returns:s
points to an array of at leasttraits::length(s) + 1
elements ofcharT
.find(basic_string_view<charT, traits>(s), pos)
. -?- Throws: Nothing.size_type find(charT c, size_type pos = 0) const noexcept;-8- Returns:
find(basic_string_view<charT, traits>(addressof(c), 1)
.(1, c), pos)
Change [string.rfind] as indicated:
size_type rfind(const charT* s, size_type pos, size_type n) const noexcept;-5- Returns:
rfind(basic_string_view<charT, traits>(s, n), pos)
.size_type rfind(const charT* s, size_type pos = npos) const;-6- Requires:
-7- Returns:s
points to an array of at leasttraits::length(s) + 1
elements ofcharT
.rfind(basic_string_view<charT, traits>(s), pos)
. -?- Throws: Nothing.size_type rfind(charT c, size_type pos = npos) const noexcept;-8- Returns:
rfind(basic_string_view<charT, traits>(addressof(c), 1)
.(1, c), pos)
Change [string.find.first.of] as indicated:
size_type find_first_of(const charT* s, size_type pos, size_type n) const noexcept;-5- Returns:
find_first_of(basic_string_view<charT, traits>(s, n), pos)
.size_type find_first_of(const charT* s, size_type pos = 0) const;-6- Requires:
-7- Returns:s
points to an array of at leasttraits::length(s) + 1
elements ofcharT
.find_first_of(basic_string_view<charT, traits>(s), pos)
. -?- Throws: Nothing.size_type find_first_of(charT c, size_type pos = 0) const noexcept;-8- Returns:
find_first_of(basic_string_view<charT, traits>(addressof(c), 1)
.(1, c), pos)
Change [string.find.last.of] as indicated:
size_type find_last_of(const charT* s, size_type pos, size_type n) const noexcept;-5- Returns:
find_last_of(basic_string_view<charT, traits>(s, n), pos)
.size_type find_last_of(const charT* s, size_type pos = npos) const;-6- Requires:
-7- Returns:s
points to an array of at leasttraits::length(s) + 1
elements ofcharT
.find_last_of(basic_string_view<charT, traits>(s), pos)
. -?- Throws: Nothing.size_type find_last_of(charT c, size_type pos = npos) const noexcept;-8- Returns:
find_last_of(basic_string_view<charT, traits>(addressof(c), 1)
.(1, c), pos)
Change [string.find.first.not.of] as indicated:
size_type find_first_not_of(const charT* s, size_type pos, size_type n) const noexcept;-5- Returns:
find_first_not_of(basic_string_view<charT, traits>(s, n), pos)
.size_type find_first_not_of(const charT* s, size_type pos = 0) const;-6- Requires:
-7- Returns:s
points to an array of at leasttraits::length(s) + 1
elements ofcharT
.find_first_not_of(basic_string_view<charT, traits>(s), pos)
. -?- Throws: Nothing.size_type find_first_not_of(charT c, size_type pos = 0) const noexcept;-8- Returns:
find_first_not_of(basic_string_view<charT, traits>(addressof(c), 1)
.(1, c), pos)
Change [string.find.last.not.of] as indicated:
size_type find_last_not_of(const charT* s, size_type pos, size_type n) const noexcept;-5- Returns:
find_last_not_of(basic_string_view<charT, traits>(s, n), pos)
.size_type find_last_not_of(const charT* s, size_type pos = npos) const;-6- Requires:
-7- Returns:s
points to an array of at leasttraits::length(s) + 1
elements ofcharT
.find_last_not_of(basic_string_view<charT, traits>(s), pos)
. -?- Throws: Nothing.size_type find_last_not_of(charT c, size_type pos = npos) const noexcept;-8- Returns:
find_last_not_of(basic_string_view<charT, traits>(addressof(c), 1)
.(1, c), pos)
Change 27.4.3.8.4 [string.compare] as indicated:
int compare(const charT* s) const noexcept;-9- Returns:
compare(basic_string_view<charT, traits>(s))
.