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

履歴 編集

customization point object
<iterator>

std::ranges::iter_swap(C++20)

namespace std {
  namespace ranges {
    inline namespace /*unspecified*/ {

      inline constexpr /*unspecified*/ iter_swap = /*unspecified*/;
    }
  }
}

概要

iter_swapはイテレータを2つ受け取り、そのイテレータの参照する要素の値を交換(swap)するカスタマイゼーションポイントオブジェクトである。

効果

まず説明専用の関数テンプレートiter-exchange-moveを次のように定義しておく。

template<class X, class Y>
constexpr iter_value_t<X> iter-exchange-move(X&& x, Y&& y)
  noexcept(noexcept(iter_value_t<X>(iter_move(x))) &&
           noexcept(*x = iter_move(y)))
{
  iter_value_t<X> old_value(iter_move(x));
  *x = iter_move(y);
  return old_value;
}

iter_swap(a, b)のように呼び出された時、以下のいずれかと等価

  1. 引数a, bのどちらかの型がクラス型であるか列挙型であり、std::ranges::iter_swap(本CPO)の宣言を含まず下記のiter_swap関数宣言を含むコンテキストで、iter_swap(a, b)が呼び出し可能ならば(void)iter_swap(a, b)

    template<class I1, class I2>
    void iter_swap(I1, I2) = delete;
    

  2. a, bの型が共にindirectly_readableのモデルであり、a, bの参照先の型がswappable_withのモデルとなるとき、ranges::swap(*a, *b)

  3. a, bの型T1, T2indirectly_movable_storable<T1, T2>indirectly_movable_storable<T2, T1>のモデルとなるとき、(void)(*a = iter-exchange-move(b, a))

  4. それ以外の場合、呼び出しは不適格。

1のケースの場合に、呼び出されるiter_swap(a, b)が交換を行わない場合、プログラムは不適格(ただし、コンパイルエラーとならない可能性がある)。

戻り値

なし

例外

上記「効果」節のそれぞれのケース毎に

  1. 呼び出されるiter_swap()が例外を投げるかに従う
  2. 引数a, b*演算子および呼び出されるranges::swap()が例外を投げるかに従う
  3. iter-exchange-move操作およびその結果の*aへの代入が例外を投げるかに従う

定数式に評価される条件

  1. 呼び出されるiter_swap()が定数評価可能かに従う
  2. 引数a, b*演算子および呼び出されるranges::swap()が定数評価可能かに従う
  3. iter-exchange-move操作およびその結果の*aへの代入が定数評価可能かに従う

カスタマイゼーションポイント

1のケースでは、ユーザー定義のiter_swap()を定義しておくことによって実行される交換操作をカスタマイズすることができる。

  1. 引数a, bの型と同じ名前空間で、もしくはHidden friendsとして、非メンバiter_swap()関数を定義しておく
  2. a, bの参照先の型についてranges::swapにアダプトしておく
  3. --

#include <iterator>
#include <vector>
#include <iostream>

int main() {
  std::vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

  std::counted_iterator ci1{std::ranges::begin(vec), 5};
  std::counted_iterator ci2{std::ranges::begin(vec) + 5, 5};

  // ケース1の呼び出し
  std::ranges::iter_swap(ci1, ci2);
  std::cout << *ci1 << ", " << *ci2 << std::endl;


  int* p1 = vec.data() + 1;
  int* p2 = p1 + 5;

  // ケース2の呼び出し
  std::ranges::iter_swap(p1, p2);
  std::cout << *p1 << ", " << *p2 << std::endl;
}

出力

6, 1
7, 2

バージョン

言語

  • C++20

処理系

参照