最終更新日時(UTC):
が更新

履歴 編集

class template
<type_traits>

std::is_swappable_with(C++17)

namespace std {
  template <class T, class U>
  struct is_swappable_with;

  template <class T, class U>
  inline constexpr bool is_swappable_with_v = std::is_swappable_with<T, U>::value;
}

概要

TUの値が、swap関数によって入れ替え可能かどうかを調べる。

要件

TUが、完全型であること。もしくはconst/volatile修飾された(あるいはされていない)voidか、要素数不明の配列型であること。

効果

TUの間でstd::swappable_with要件を満たしていればtrue_typeから派生し、そうでなければfalse_typeから派生する。

TUは参照でなければswapできないのでTUが参照でない場合、結果はfalseとなる。

簡単に説明するとstd::swappable_with要件を満たすとは、2引数を取りその引数の値を入れ替えるswap関数が以下のようなコードで見つかることである。

#include <utility>

template<typename T, typename U>
swappable_with(T& t, U& u) {
  using std::swap;

  //非メンバ関数のswap(t, u)が見つかる必要がある
  swap(t, u);
  //tとuは入れ替わっている

  //引数を逆にしても同じく見つかる必要がある
  swap(u, t);
  //tとuは呼び出し時と同じに戻る
}

備考

このメタ関数はTUについてのswap関数の直接のコンテキストの妥当性(そのシグネチャで有効なswapがあるかどうか)のみをチェックする。そのため、結果がtrueとなったとしてもswap関数の呼び出しができることは保証されない(その他の要因によりコンパイルエラーが発生する可能性がある)。

また同様に、結果がtrueとなっても見つかったswap関数がswap動作をするかどうかも保証しない。

#include <type_traits>
#include <iostream>

template<typename T>
struct non_swappable {};

template<typename T>
void swap(int&, non_swappable<T>&){}

template<typename T>
void swap(non_swappable<T>& lhs, int& rhs) {
  int a = rhs;
  //以下の代入は定義されていない
  rhs = lhs;
  lhs = a;
}

int main()
{
  std::cout << std::boolalpha;

  std::cout << std::is_swappable_with<int&, int&>::value << std::endl;

  //参照でなければならない
  std::cout << std::is_swappable_with<int, int>::value << std::endl;

  std::cout << std::is_swappable_with<int&, double&>::value << std::endl;

  //実際には呼び出し不可であり、swap動作もしないが、定義が見つかるためにtrueになる
  std::cout << std::is_swappable_with<non_swappable<int>&, int&>::value << std::endl;
  std::cout << std::is_swappable_with<int&, non_swappable<int>&>::value << std::endl;

  //ここのコメントを外すとコンパイルエラー
  /*non_swappable nonswap{};
  int n{};
  swap(nonswap, n);*/
}

出力

true
false
false
true
true

バージョン

言語

  • C++17

処理系

  • Clang: ??
  • GCC: ??
  • Visual C++: 2015 update3, 2017
    • 2015 update3では、インテリセンスで表示されないが変数テンプレート共々定義されており利用可能である

参照