【问题标题】:Why is there not a no-throw guarantee in the standard for std::set::extract() and std::set::insert(nh)?为什么 std::set::extract() 和 std::set::insert(nh) 的标准中没有不抛出保证?
【发布时间】:2021-07-05 23:00:01
【问题描述】:

在 C++20 (N4849) 中,关联容器的 extract()insert(node_handle)/insert(hint, node_handle) 方法没有例外安全措辞。

但是对于merge(),有这样的措辞:

抛出:除非比较对象抛出,否则什么都没有。

位置:
22.2.6 关联容器 [associative.reqmts]
表 78:关联容器要求(除了容器)[tab:container.assoc.req]
第 799 页

显然,最初的提议 (P0083R3) 旨在使其不投掷(第 5 页):

异常安全

如果容器的 Compare 函数是 no-throw(这很常见),那么移除一个节点、修改它并插入它就是 no-throw,除非修改值 throws。如果修改值确实抛出,它会在所涉及的容器之外这样做。

但为什么该提案后面的措辞没有发言权?

【问题讨论】:

  • 请注意,与merge() 不同,extract() 必须复制容器的分配器。但是分配器模型要求复制是 noexcept。看起来extract() 可能是 noexcept 如果比较器是。

标签: c++ language-lawyer c++20 splice throws


【解决方案1】:

获取节点句柄的insert 成员有一个先决条件,即节点句柄中的分配器与容器的分配器比较相等。

采用迭代器的extract 成员有一个先决条件,即该迭代器是容器中的有效可解引用迭代器。

标准库的政策是有运行时前置条件的函数不是noexcept

带有key_type 参数的extract 成员只有在比较函数抛出时才能抛出,但这仍然意味着它不能是noexcept

【讨论】:

  • 这与方法签名中的 noexcept 说明符无关。这是关于标准中的一项声明,承诺在满足某些先决条件时不允许出现异常。例如,标准对std::list::splice() 有这个:“void splice(const_iterator position, list& x, const_iterator i)前提条件ix 的有效可解引用迭代器。抛出:没有。”(n4849 第 832 页,[ list.ops]) 目前标准中不存在set/mapextract()/insert()这样的声明。
猜你喜欢
  • 1970-01-01
  • 2021-10-04
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 2014-03-15
  • 1970-01-01
  • 2011-07-20
  • 1970-01-01
相关资源
最近更新 更多