As of N3797 the C++ standard requires swap
functions of containers to not throw any exceptions unless specified otherwise [container.requirements.general]
(23.2.1§10).
swap
member functions that are specified to not throw not declared noexcept
?The same question applies to the specialized non-member swap
overloads.
Further to what refp said, here's a post from Daniel Krügler on the std-discussion
mailing list:
The internal policy to declare a function as unconditional noexcept is explained in
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3279.pdf
With the terminology used in that paper, std::vector's swap function has a narrowing contract, that is it has preconditions in regard to the allocators of the participating objects. This means, there exists the possibility that callers may violate the preconditions and an implementation should be allowed to signal this my different means than by termination. Therefore such functions should not be noexcept, but it should have an effective element "Throws: Nothing" because this applies to the situation when the preconditions are satisfied.
(link)
Said internal policy is the canonical, official answer to your question.
It may sound odd at first, but not explicitly stating that swap
of standard container is noexcept
is intentional; and it all boils down to undefined behavior (UB).
23.2.1p9
General Container Requirements[container.requirements.general]
The expression
a.swap(b)
, for containersa
andb
of a standard container type other thanarray
, shall exchange the values ofa
andb
without invoking any move, copy, or swap operations on the individual container elements.Any
Compare
,Pred
, orHash
objects beloning toa
andb
shall be swappable and shall be exchanged by unqualified calls to non-memberswap
.If
allocator_traits<allocator_type>::propagate_on_container_swap::value
istrue
, then the allocators ofa
andb
shall also be exchanged using an unqalified call to non-memberswap
. Otherwise, they shall not be swapped, and the behavior is undefined unless `a.get_allocator () == b.get_allocator ().
Note: italics added by me.
Why is the previous section relevant to my question?
Since the swap
of standard containers has a precondition (most importantly the last paragraph of the previously quoted section of the Standard), that may lead to UB if not satisfied, the Standard doesn't want to impose "impossible" constraints on implementations.
The Standard says the following about undefined behaviour:
1.3.24
undefined behavior[defns.undefined]
Behavior for which this International Standard imposes no requirements.
Only criminals, and perhaps salesmen, would consider a No to be something other than a No, but when the Standard says "no requirements" it really means "no requirements"; marking the relevant swap
functions as noexcept
would impose a requirement on implementations, where there should be none.
Why doesn't the Standard want to impose such requirements?
There's an interesting paper (N3248) on this matter by Alisdair Meredith and John Lakos titled "noexcept
prevents Library Validation".
In short it talks about how noexcept
will prevent library implementation to use asserts
in library code (ie. implementations of the standard library), even during debug mode, and the implications of that.
If C++ had a standardized "testing" vs "production" mode (as the paper calls it), where noexcept
would conditionally apply, this would be far less problematic.. but as it currently stands; C++ has no "modes".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With