標準ライブラリの実装で追加のnoexceptが付いている場合がある

標準ライブラリの仕様でnoexceptが付いているものは、実装にもnoexceptを付けることが求められます。

しかし、標準ライブラリの仕様でnoexceptが付いていない場合、実装にnoexceptを付けないことは求められません。

たとえば、libc++のstd::vectorクラスでは、以下のメンバ関数noexceptが付いています。

// https://github.com/llvm-mirror/libcxx/blob/018a3d51a47f7275c59e802709104498b729522b/include/vector

vector()
    noexcept(is_nothrow_default_constructible<allocator_type>::value);

vector(vector&& x)
    noexcept(is_nothrow_move_constructible<allocator_type>::value);

vector& operator=(vector&& x)
    noexcept(
         allocator_type::propagate_on_container_move_assignment::value ||
         allocator_type::is_always_equal::value);

void shrink_to_fit() noexcept;

void swap(vector&)
    noexcept(allocator_traits<allocator_type>::propagate_on_container_swap::value ||
             allocator_traits<allocator_type>::is_always_equal::value);

libstdc++のstd::vectorクラスでは、以下のメンバ関数noexceptが付いています。

// https://github.com/gcc-mirror/gcc/blob/67886b40399e79bcc392a152e96d9116ba24e2ed/libstdc%2B%2B-v3/include/bits/stl_vector.h

vector()
    noexcept(is_nothrow_default_constructible<_Alloc>::value);

vector(vector&& __x) noexcept;

vector(vector&& __rv, const allocator_type& __m)
    noexcept(_Alloc_traits::_S_always_equal());

vector&
    operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move());

// swapで例外を投げそうなアロケータはコンパイルエラー
void swap(vector& __x) _GLIBCXX_NOEXCEPT;

これにより、特定の標準ライブラリを使用する場合に、例外を投げない強い保証をするコードを書けることがあります (とくにデフォルトコンストラクタが有用)。また、仕様でnoexceptが付いていない関数に対して、noexcept(式)で例外を投げないかチェックすることにも意義があります。