namespace std {
namespace ranges {
inline namespace /*unspecified*/ {
inline constexpr /*unspecified*/ iter_move = /*unspecified*/;
}
}
}
概要
iter_move
はイテレータを1つ受け取り、そのイテレータの参照する要素の値を移動(move
)するカスタマイゼーションポイントオブジェクトである。
効果
iter_move(i)
のように呼び出された時、以下のいずれかと等価
-
引数
i
の型がクラス型であるか列挙型であり、std::ranges::iter_move
(本CPO)の宣言を含まず下記のiter_move
関数宣言を含むコンテキストで、iter_move(i)
が呼び出し可能ならばiter_move(i)
void iter_move();
-
*i
が有効であり、*i
の結果が左辺値であるならばstd::move(*i)
-
*i
が有効であり、*i
の結果が右辺値であるならば*i
-
それ以外の場合、呼び出しは不適格。
1のケースの場合に、呼び出されるiter_move()
が移動しようとする値を変更する場合、プログラムは不適格(ただし、コンパイルエラーとならない可能性がある)。
戻り値
引数i
の指す要素の(右辺値)参照、もしくはi
の指す要素を移動した値
例外
上記「効果」節のそれぞれのケース毎に
- 呼び出される
iter_move()
が例外を投げるかに従う - 引数
i
についての*
演算子が例外を投げるかに従う - 引数
i
についての*
演算子が例外を投げるかに従う
定数式に評価される条件
- 呼び出される
iter_move()
が定数評価可能かに従う - 引数
i
についての*
演算子が定数評価可能かに従う - 引数
i
についての*
演算子が定数評価可能かに従う
カスタマイゼーションポイント
- 引数
i
の型と同じ名前空間で、もしくはHidden friendsとして、非メンバiter_move()
関数を定義しておく - --
- --
備考
一見するとこの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
処理系
- Clang: ??
- GCC: 10.1 ✅
- Visual C++: 2019 Update 4 ✅