According to [string.find#1.2] and [string.find#1.3]:
Each member function of the form
constexpr size_type F(const charT* s, size_type pos) const;
has effects equivalent to:
return F(basic_string_view<charT, traits>(s), pos);
Each member function of the form
constexpr size_type F(const charT* s, size_type pos, size_type n) const;
has effects equivalent to:
return F(basic_string_view<charT, traits>(s, n), pos);
Those two find
functions are not declared as noexcept
, but all of three compiler vendors didn't follow the rule, they just implement it as noexcept
.
What is the reason behind this?
This is the so-called Lakos rule. See N3248. The rule is that if a function has a precondition, it should not be marked noexcept
because it prevents an implementation from checking the precondition and throwing an exception on validation, if the implementation would choose to do that.
In this case, find(s, pos, n)
is equivalent to find(string_view(s, n), pos)
. And that string_view(s, n)
construction has a precondition that s
is a valid string of length at least n
. So an implementation could try to validate that somehow and throw an exception on failure.
But none of the implementations actually try to validate this, so they don't take the freedom of potentially throwing on precondition violation, and instead simply mark these functions as noexcept
. Which they're allowed to do from [res.on.exception.handling]:
An implementation may strengthen the exception specification for a non-virtual function by adding a non-throwing exception specification.
Library Evolution has recently accepted P1656 which basically reverts the Lakos Rule.