为什么这两个 std::string find() 函数被声明为 noexcept?
Why those two std::string find() functions are declared as noexcept?
根据[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);
那两个 find
函数没有声明为 noexcept
,但是三个编译器供应商的 all 没有遵守规则,他们只是将其实现为 noexcept
.
这背后的原因是什么?
好的,我找到答案了。
根据 [res.on.exception.handling]:
An implementation may strengthen the exception specification for a non-virtual function by adding a non-throwing exception specification.
所以他们可以自由标记这个过载noexcept
。感谢您的关注。
这就是所谓的拉科斯法则。参见 N3248。规则是,如果函数有前提条件,则不应将其标记为 noexcept
,因为如果实现选择这样做,它会阻止实现检查前提条件并在验证时抛出异常。
在这种情况下,find(s, pos, n)
等同于 find(string_view(s, n), pos)
。 string_view(s, n)
构造的前提条件是 s
是长度至少为 n
的有效字符串。所以一个实现 可以 尝试以某种方式验证它并在失败时抛出异常。
但是 none 的实现实际上试图验证这一点,因此他们没有采取可能抛出前提条件违规的自由,而是简单地将这些函数标记为 noexcept
。他们被允许从 [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 最近接受了 P1656,这基本上恢复了 Lakos 规则。
根据[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);
那两个 find
函数没有声明为 noexcept
,但是三个编译器供应商的 all 没有遵守规则,他们只是将其实现为 noexcept
.
这背后的原因是什么?
好的,我找到答案了。
根据 [res.on.exception.handling]:
An implementation may strengthen the exception specification for a non-virtual function by adding a non-throwing exception specification.
所以他们可以自由标记这个过载noexcept
。感谢您的关注。
这就是所谓的拉科斯法则。参见 N3248。规则是,如果函数有前提条件,则不应将其标记为 noexcept
,因为如果实现选择这样做,它会阻止实现检查前提条件并在验证时抛出异常。
在这种情况下,find(s, pos, n)
等同于 find(string_view(s, n), pos)
。 string_view(s, n)
构造的前提条件是 s
是长度至少为 n
的有效字符串。所以一个实现 可以 尝试以某种方式验证它并在失败时抛出异常。
但是 none 的实现实际上试图验证这一点,因此他们没有采取可能抛出前提条件违规的自由,而是简单地将这些函数标记为 noexcept
。他们被允许从 [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 最近接受了 P1656,这基本上恢复了 Lakos 规则。