If my math is correct, there are 125 changes / fixes / new features in C++23 and we are progressively covering them on this blog. I try to go from topic to topic. There are some topics with many smaller changes, such as constexpr
, there are some significant topics where even one topic must be in its own post such as the stacktrace library, and there are also some shorter posts with few and quite small changes on a given topic. Today we are going to discuss noexcept
related changes.
If you haven't read it, I'd recommend reading my article on
noexcept
and its effects on binary size
We can definitely see two trends in the proposals accepted for the latest standards. They try to make more and more functions:
-
constexpr
, and noexcept
The two main changes presented today fit into this trend. But let's start with discussing a bit of noexcept
policies in the standard.
noexcept
, but with conditions
The current policies on whether something in the standard can be noexcept
or not is defined by P1656R2. Let me summarize the gist of it here.
As we got used to it, a destructor should never throw and therefore even if you don't mark it noexcept
they implicitly are!
There might be standard library functions marked unconditionally noexcept
if the committee fully agrees that the given function cannot throw.
The standard specifies a couple of special member functions and library functions that can be marked conditionally noexcept
, based on the underlying types and the types these functions operate on. Nothing else can be marked noexcept
, except for library functions that are designed for compatibility with C. Those can be unconditionally noexcept
.
Most often, we mark functions either
noexcept
or not. So we often mark our functions unconditionallynoexcept
. Butnoexcept
can take a compile-time computable condition, such asstd::is_nothrow_move_constructible_v<T> && std::is_nothrow_assignable_v<T&, U>
Here is the list that can be marked conditionally noexcept
according to C++20.
std::swap
- the copy-constructor and -assignment operator
- the move-constructor and -assignment operator
This list is getting modified in the C++23 standard.
It's also worth noting that an implementation can mark conditionally noexcept
a function even if it's not listed by the standard so.
Add a conditional noexcept specification to std::exchange
One of the primary use cases for std::exchange
is implementing the move constructor and move assignment operator. In a certain way, it's quite similar to std::swap
. Yet, while std::swap
and move operations can be conditionally noexcept
, it was not the case for std::exchange
.
Up until C++23.
P2401R0 makes std::exchange
conditionally noexcept
. The conditions are the same as for move operations: is_nothrow_move_constructible_v<T> && is_nothrow_assignable_v<T&, U>
.
Add a conditional noexcept specification to std::apply
With the introduction of zip
algorithms in C++23, people in and around the committee started to talk once again more and more about std::apply
.
The reason is that std::apply
could be effectively used to implement these new algorithms. In fact, in the previously referenced proposal apply
appears quite a few times. Sadly, std::apply
is not noexcept
.
But, if we have a look into the exposition-only implementation of apply
, we can see that it uses invoke
and get
. The latter is noexcept
and the former is conditionally noexcept
, so there is no reason why std::apply
should not be conditionally noexcept
.
And that becomes the new reality with C++23:
template<class F, class Tuple>
constexpr decltype(auto) apply(F&& f, Tuple&& t) noexcept(see below);
// Let I be the pack 0, 1, ..., (tuple_size_v<remove_reference_t<Tuple>>-1). The exception specification is equivalent to: noexcept(invoke(std::forward<F>(f), get<I>(std::forward<Tuple>(t))...)).
Conclusion
In this article, we reviewed how the standard defines its policies towards the noexcept
specification and we also see that two standard library functions (std::apply
and std::exchange
) are becoming noexcept
.
Connect deeper
If you liked this article, please
- hit on the like button,
- subscribe to my newsletter
- and let's connect on Twitter!