読者です 読者をやめる 読者になる 読者になる

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

C++

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

condition_variableのwait系関数が例外を送出する仕様を変更

C++11までは、ミューテックスの取得関係で例外が送出される可能性があった。

C++14では、ミューテックスの取得関係では、wait系関数は例外を送出しない。その代わりにstd::terminate()関数を呼び出してプログラムが異常終了する。時計、時間演算関係で例外を送出する可能性がある。

tuple_sizeの特殊化が、必ずintegral_constantから派生するようになった

namespace std {
  template <class T> class tuple_size; // 先行宣言

  // C++11
  struct tuple_size<pair<T1, T2>> {
    static constexpr size_t value = 2;
  };

  // C++14
  struct tuple_size<pair<T1, T2>>
    : public integral_constant<size_t, 2> {};
}
namespace std {
  template <class T> class tuple_size; // 先行宣言

  // C++11
  template <class T, size_t N>
  struct tuple_size<array<T, N>> {
    static constexpr size_t value = N;
  };

  // C++14
  template <class T, size_t N>
  struct tuple_size<array<T, N>>
    : integral_constant<size_t, N> {};
}

is_null_pointer型特性を追加

ヌルポインタ型かを判定するis_null_pointer型特性が、<type_traits>に追加されました。

namespace std {
  template <class T> 
  struct is_null_pointer;
}

この型特性は、型Tstd::nullptr_tであればstd::true_typeから派生し、そうでなければstd::false_typeから派生します。

copy_ifに戻り値の仕様を追加

C++11で追加されたアルゴリズムstd::copy_if()ですが、戻り値の仕様が未規定だったので、C++14で以下の仕様が追加されました。

戻り値
コピー先の範囲の終端を返す。

mem_fnの不要なオーバーロードを削除

C++11:

namespace std {
  template<class R, class T> unspecified mem_fn(R T::*);
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...));
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...) const);
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...) volatile);
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...) const volatile);
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...) &);
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...) const &);
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...) volatile &);
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...) const volatile &);
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...) &&);
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...) const &&);
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...) volatile &&);
  template<class R, class T, class... Args>
  unspecified mem_fn(R (T::*)(Args...) const volatile &&);
}

C++14:

namespace std {
  template<class R, class T>
  unspecified mem_fn(R T::*);
}

単に冗長なオーバーロードでした。

functionに、異なるシグニチャの関数オブジェクトが代入された際の挙動を追加

以下のオーバーロードについて、

template <class F>
function(F f);

template <class F, class Alloc>
function(allocator_arg_t, const Alloc& alloc, F f);

C++11までは、型Fstd::functionのテンプレートパラメータと同じシグニチャを持つことを「要件」として定義していました。

C++14では、異なるシグニチャの関数オブジェクトが渡された場合、オーバーロード解決の候補から外れます(SFINAEになる)。

こちらもC++14では以下のオーバーロードについて、

template<class F>
function& operator=(F&& f);

異なるシグニチャの関数オブジェクトが渡された場合、オーバーロード解決の候補から外れます。

vector<bool>にemplaceとemplace_backを追加

単に書き忘れです。

cpprefjpにどう書こうか悩んだのですが、暫定的に、std::vectorの各メンバ関数のページに書きました。

template <class... Args>
iterator emplace(const_iterator position, Args&&... args);

template <class... Args>
iterator vector<bool>::emplace(const_iterator position, Args&&... args); // C++14
template <class... Args>
void emplace_back(Args&&... args);

template <class... Args>
void vector<bool>::emplace_back(Args&&... args); // C++14

今日はここまで

ひとまずネタが尽きたのですが、cpprefjp側の対応が進んだらもう少し書きます。