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

履歴 編集

customization point object
<iterator>

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

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

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

概要

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

効果

iter_move(i)のように呼び出された時、以下のいずれかと等価

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

    void iter_move();
    

  2. *iが有効であり、*iの結果が左辺値であるならばstd::move(*i)

  3. *iが有効であり、*iの結果が右辺値であるならば*i

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

1のケースの場合に、呼び出されるiter_move()が移動しようとする値を変更する場合、プログラムは不適格(ただし、コンパイルエラーとならない可能性がある)。

戻り値

引数iの指す要素の(右辺値)参照、もしくはiの指す要素を移動した値

例外

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

  1. 呼び出されるiter_move()が例外を投げるかに従う
  2. 引数iについての*演算子が例外を投げるかに従う
  3. 引数iについての*演算子が例外を投げるかに従う

定数式に評価される条件

  1. 呼び出されるiter_move()が定数評価可能かに従う
  2. 引数iについての*演算子が定数評価可能かに従う
  3. 引数iについての*演算子が定数評価可能かに従う

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

  1. 引数iの型と同じ名前空間で、もしくはHidden friendsとして、非メンバiter_move()関数を定義しておく
  2. --
  3. --

備考

一見するとこのCPOは冗長であるように見えるが、イテレータiについての*iの結果がprvalueを返す(イテレータの要素型Tのオブジェクトをそのまま返す)場合に不要なキャストを回避することでより効率的なムーブ(コピー省略による直接構築)を行うことができる。

イテレータを利用したジェネリックなアルゴリズムの実装においてイテレータの要素をムーブする必要がある場合には、std::move(*i)のようなコードを直接書くよりもこのCPOを使用したほうがより効率的になりうる。

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

struct I {
  int n = 0;

  // Hidden friendsとして定義、prvalueを返す
  friend auto iter_move(I& self) -> I {
    return std::move(self);
  }

  I& operator*();
};

int main() {
  I i = {20};

  // ケース1の呼び出し
  I i2 = std::ranges::iter_move(i);

  std::cout << i2.n << std::endl;

  std::vector vec = {1, 2, 3, 4};

  // ケース2の呼び出し
  int n = std::ranges::iter_move(vec.begin());

  std::cout << n << std::endl; 
}

出力

20
1

バージョン

言語

  • C++20

処理系

参照