Is conditional noexcept only for swap function, move-constructor, or move-assignment operator?
However, according to
cppreference, it is useful for any function templates.
The noexcept keyword was introduced in order to solve a problem with C++11 std::vector (as compared to C++98 std::vector). That problem (the "vector pessimization") applies only to the move constructor. (Well, and the destructor; but C++11 decided to make destructors noexcept by default, and the C++11 STL decided not to care at all about types whose destructors weren't noexcept.)
It is traditional to mark your move-assignment operator and your ADL `swap` functions also with `noexcept` (and to make it conditional if you're writing a template where those operations are only sometimes noexcept), but there is no particular engineering reason to do so — nothing in the standard library actually cares whether those operations are noexcept or not.
See:
The standard library sometimes marks functions as `noexcept` so that they don't "get in the way of" the user-programmer's attempts to determine the noexceptness of a complicated expression; e.g.
struct S { int f() noexcept; };
std::unique_ptr<S> p;
static_assert(noexcept(p->f())); // OK
works only because `std::unique_ptr<S>::operator->() const` is marked `noexcept` in the library. But this is at least 50% ad-hoc; for example, notice that unique_ptr's
`operator*` and `operator->` are marked (conditionally) noexcept, but its `
operator[]` is not.
std::unique_ptr<S[]> pa;
static_assert(!noexcept(pa[0].f())); // except on MSVC
–Arthur