C++1z コンテナのコピー・ムーブ、swap操作にnoexceptを追加

C++14までコンテナのnoexceptは最小限でしたが、C++1zではアロケータのコピーやムーブが例外を投げる可能性があるかどうかに基づいて、noexceptが追加されます。これで、標準ライブラリを使用したプログラムがより強い例外安全性を保証できるようになります。

まず、アロケータ側。ユーザーが定義するアロケータの要件として、is_always_equalという型をstd::true_typeの別名として定義すれば、同じ型のアロケータオブジェクトが2つある場合、それらが常に同値であるという表明になります。これは同時に、アロケータが状態を持たずコピーやムーブが例外を投げる可能性がないという表明にもなります。

struct MyAllocator {
    …
    using is_always_equal = std::true_type;
};

標準のstd::allocatorクラスのis_always_equalstd::true_typeとなります。

次にアロケータのデフォルトインタフェースと中間インタフェースを提供するstd::allocator_traitsクラスには、ユーザー定義のアロケータにis_always_equalが定義されない場合のデフォルトが定義されます。デフォルトではstd::is_empty型特性の結果型が設定されます。つまり、メンバ変数を持たないようなアロケータは自動的にis_always_equalが真になります。

template <class Alloactor>
struct allocator_traits {
    …
    using is_always_equal = /* Allocator::is_always_equalが定義されていればその別名となり、
                               そうでなければis_empty<Allocator> */;
};

コンテナ側に追加されるnoexceptは、以下のようになります。

  • basic_string, vector
    • デフォルトコンストラクタ (無条件でnoexcept)
    • アロケータを受け取るコンストラクタ (無条件でnoexcept)
    • ムーブコンストラクタ
    • ムーブ代入演算子
    • swap()
    • メンバ関数版のswap()
  • deque, forward_list, list, map, multimap, set, multiset, unordered_map, unordered_multimap, unordered_set, unordered_multiset

参照

お断り

この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。