In N3421 - Making Operator Functors greater<>, the new specialization for the std function objects is:
template <> struct plus<void> {
template <class T, class U> auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) + std::forward<U>(u));
};
instead of
template <> struct plus<void> {
template <class T, class U> auto operator()(T&& t, U&& u) const
noexcept(noexcept(decltype(std::forward<T>(t) + std::forward<U>(u))
(std::move(std::forward<T>(t) + std::forward<U>(u)))))
-> decltype(std::forward<T>(t) + std::forward<U>(u));
};
- Is there a reason for that?
- Does the omission of
noexcept
matter in this use case?
Edit: link to the working draft line in github.
Edit 2: link to libc++ plus specialization.
The existing LWG guidelines do not encourage the use of noexcept. They do not accept noexcept on wide-contract functions, only narrow-contract ones. I don't recall exactly how these terms were defined, but I can tell you that I was present at the Bristol meeting discussing noexcept
and they refused to place it on a function because it was wide-contract, which I considered to be batshit insane.
So it's probably not on here for one of two reasons. The first is that the Committee and paper authors are not yet used to considering noexcept
in every case- similar to constexpr
. In this case, the paper author (STL) probably simply forgot to add it.
The second is that LWG has some insane over-restrictions on when they will accept noexcept
.
@DeadMG's answer led me to Conservative use of noexcept in the Library, which says the following:
Adopted Guidelines
No library destructor should throw. They shall use the implicitly supplied (non- throwing) exception specification.
Each library function having a wide contract, that the LWG agree cannot throw, should be marked as unconditionally noexcept.
If a library swap function, move-constructor, or move-assignment operator is conditionally-wide (i.e. can be proven to not throw by
applying the noexcept operator) then it should be marked as
conditionally noexcept. No other function should use a conditional
noexcept specification.
Library functions designed for compatibility with “C” code (such as the atomics facility), may be marked as unconditionally noexcept.
where narrow and wide contracts are defined as:
A wide contract for a function or operation does not specify any undefined behavior. Such a contract has no preconditions: A function
with a wide contract places no additional runtime constraints on its
arguments, on any object state, nor on any external global state.
A narrow contract is a contract which is not wide. Narrow contracts for a functions or operations result in undefined behavior when called
in a manner that violates the documented contract. Such a contract
specifies at least one precondition involving its arguments, object
state, or some external global state, such as the initialization of a
static object.
At the end of that document, operators functors previously marked noexcept
are no longer noexcept
.
So if I understand this correctly, the new operators functors in <functional>
have wide-contracts, but might throw sometimes depending on the types they act on. As such, they are not unconditionally noexcept(true)
. Due to this, it is left to the library implementors to decide:
their use be left as a library vendor quality-of-implementation
feature until we have more experience.