C++14標準ライブラリの小さな変更 その2

その1に引き続き、C++14の標準ライブラリに入った、小さな変更を紹介していきます。

weak_ptrがムーブに対応した

C++14では、弱参照スマートポインタのstd::weak_ptrクラスに、以下のコンストラクタと、

weak_ptr(weak_ptr&& r) noexcept;

template <class Y>
weak_ptr(weak_ptr<Y>&& r) noexcept;

以下の代入演算子が追加されました。

weak_ptr& operator=(weak_ptr&& r) noexcept;

template <class Y>
weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;

これまで、weak_ptrはコピーはできたので、既存コードに影響はありません。

細かいnoexceptの付け忘れ対応

constexpr operator value_type()          { return value; } // C++11
constexpr operator value_type() noexcept { return value; } // C++14
  • <ios>ヘッダの以下の関数に、noexceptが追加されました。

iostream_category()関数 : 入出力のエラーカテゴリオブジェクトを作って返す。

namespace std {
  const error_category& iostream_category();          // C++11
  const error_category& iostream_category() noexcept; // C++14
}

make_error_code()関数 : 入出力関係のエラーコードを作って返す。

namespace std {
  error_code make_error_code(io_errc e);          // C++11
  error_code make_error_code(io_errc e) noexcept; // C++14
}

make_error_condition()関数 : 入出力関係のエラーコードに紐づく情報を、作って返す。

namespace std {
  error_condition make_error_condition(io_errc e);          // C++11
  error_condition make_error_condition(io_errc e) noexcept; // C++14
}

メンバ関数版の組み込み配列用begin()end()に、noexceptが追加されました。

namespace std {
  template <class T, size_t N>
  T* begin(T (&array)[N]);                    // C++11

  template <class T, size_t N>
  constexpr T* begin(T (&array)[N]) noexcept; // C++14
}
namespace std {
  template <class T, size_t N>
  T* end(T (&array)[N]);                    // C++11

  template <class T, size_t N>
  constexpr T* end(T (&array)[N]) noexcept; // C++14
}

future_errcの開始値が0ではなくなった

C++11で<future>ヘッダに追加された、futurepromise関係のエラー値列挙型std::future_errcですが、列挙値が実装定義になりました。

C++11:

namespace std {
  // C++11
  enum class future_errc {
    broken_promise,
    future_already_retrieved,
    promise_already_satisfied,
    no_state
  };
}

C++14:

namespace std {
  enum class future_errc {
    broken_promise = implementation-defined,
    future_already_retrieved = implementation-defined,
    promise_already_satisfied = implementation-defined,
    no_state = implementation-defined
  };
}

この変更は、std::future_errcの値をstd::error_codeオブジェクトに入れたときに、開始値が0だと困るからです。

始値broken_promiseは、正常値ではなくエラー値です。これが0だと困るのは、std::error_codeクラスのoperator bool()が、以下の仕様になっていることです。

explicit operator bool() const noexcept;

戻り値:
return value() != 0

つまり、0を正常値、0以外をエラー値としています。

そのため、C++11のbroken_promisestd::error_codeに設定すると、エラー値なのに正常値と見なされてしまいます。

C++14のこの変更で、std::future_errcのいずれの値も0以外になります。

今日はこれまで

さらに続きます。