Why is there not a no-throw guarantee in the standard for std::set::extract() and std::set::insert(nh)?
Asked Answered
C

1

10

In C++20 (N4849), there is no exception safety wording for associative containers' extract() and insert(node_handle)/insert(hint, node_handle) methods.

But for merge(), there is this wording though:

Throws: Nothing unless the comparison object throws.

Location:
22.2.6 Associative containers [associative.reqmts]
Table 78: Associative container requirements (in addition to container) [tab:container.assoc.req]
Page 799

Apparently the orignal proposal (P0083R3) intended to make it no-throw (page 5):

Exception safety

If the container’s Compare function is no-throw (which is very common), then removing a node, modifying it, and inserting it is no-throw unless modifying the value throws. And if modifying the value does throw, it does so outside of the containers involved.

But why is there no say in the proposed wording later in that proposal?

Coldhearted answered 10/4, 2021 at 7:7 Comment(1)
Note that unlike merge(), extract() has to copy the container's allocator. But the Allocator model requires that copying be noexcept. It does seem like extract() could be noexcept if the comparator is.Sedate
B
4

The insert members taking a node handle have a precondition that the allocator in the node handle compares equal to the container's allocator.

The extract members taking an iterator have a precondition that the iterator is a valid dereferenceable iterator into the container.

The policy of the standard library is that functions with runtime preconditions are not noexcept.

The extract member taking a key_type argument can only throw if the comparison function throws, but that still means it can't be noexcept.

Betti answered 19/4, 2021 at 10:25 Comment(1)
It's not about a noexcept specifier in the method signature. It's about a statement in the standard promising that no exception is allowed when certain preconditions are met. For example, the standard has this for std::list::splice(): "void splice(const_iterator position, list& x, const_iterator i), Preconditions: i is a valid dereferenceable iterator of x. Throws: Nothing."(n4849 page 832, [list.ops]) For now no such statement exists for set/map's extract()/insert() in the standard.Coldhearted

© 2022 - 2024 — McMap. All rights reserved.