イテレーターは、oneapi/dpl/iterator ヘッダーで定義されています。すべてのイテレーターは、oneapi::dpl 名前空間で実装されています。
counting_iterator: 逆参照値が整数カウンターであるランダム・アクセス・イテレーターのような型です。counting_iterator のインスタンスは、読み取り専用の逆参照操作を提供します。counting_iterator インスタンスのカウンターは、ランダム・アクセス・イテレーター型の演算に応じて変化します。
using namespace oneapi;
dpl::counting_iterator<int> count_a(0);
dpl::counting_iterator<int> count_b = count_a + 10;
int init = count_a[0]; // OK: init == 0
*count_b = 7; // エラー: counting_iterator は書き込み操作を提供しません
auto sum = std::reduce(dpl::execution::dpcpp_default,
count_a, count_b, init); // sum is (0 + 0 + 1 + ...+ 9) = 45
zip_iterator: 1 つ以上のイテレーターを入力として構築されるイテレーターです。zip_iterator 逆参照の結果は、zip_iterator がラップする、メンバー・イテレーターの逆参照によって返される値を保持する不特定型のタプル形式のオブジェクトです。zip_iterator インスタンスに対して実行された算術演算は、各メンバー・イテレーターにも適用されます。
zip_iterator インスタンスを容易に構築できるように、make_zip_iterator 関数が提供されています。関数は、zip_iterator インスタンスとメンバー・イテレーターとして保持するすべての引数を返します。
zip_iterator は、キーと値を表す入力イテレーターがキーと値のペアとして処理されるキー・アルゴリズムの定義に役立ちます。以下の例は、キーのみを比較してキーと値の両方をスワップする、安定したキーによるソートです。
using namespace oneapi;
auto zipped_begin = dpl::make_zip_iterator(keys_begin, vals_begin);
std::stable_sort(dpl::execution::dpcpp_default, zipped_begin, zipped_begin + n,
[](auto lhs, auto rhs) { return get<0>(lhs) < get<0>(rhs); });
zip_iterator の逆参照オブジェクトは、ラップされたイテレーター値に簡単にアクセスできる構造化束縛機能 (C++17 以降) (英語) をサポートしています。
using namespace oneapi;
auto zipped_begin = dpl::make_zip_iterator(sequence1.begin(), sequence2.begin(), sequence3.begin());
auto found = std::find(dpl::execution::dpcpp_default, zipped_begin, zipped_begin + n,
[](auto tuple_like_obj) {
auto [e1, e2, e3] = tuple_like_obj;
return e1 == e2 && e1 == e3;
}
);
zip_iterator の逆参照は意味的には参照のタプルであるため、そのようなオブジェクトのコピーは低コストであると想定されます。上記の例で、e1、e2 および e3 は参照です。
zip_iterator の使用例は、以下の discard_iterator のコード例を参照してください。
discard_iterator: 渡された値を破棄する書き込み専用の逆参照操作を提供するランダム・アクセス・イテレーターのような型です。
discard_iterator は、ステンシルが出力の一部ではないステンシル・アルゴリズムの実装に役立ちます。一例として、入力イテレーターの範囲とステンシル・イテレーターの範囲を受け取り、ステンシル値が 1 の入力要素をコピーする copy_if アルゴリズムが挙げられます。discard_iterator を使用すると、ステンシルのコピーを格納する一時割り当てを宣言しなくても済みます。
using namespace oneapi;
auto zipped_first = dpl::make_zip_iterator(first, stencil);
std::copy_if(dpl::execution::dpcpp_default,
zipped_first, zipped_first + (last - first),
dpl::make_zip_iterator(result, dpl::discard_iterator()),
[](auto t){return get<1>(t) == 1;}
transform_iterator: 逆参照値がオリジナルのイテレーターの対応する要素に関数を適用した結果である、別のイテレーター上で定義されるイテレーターです。元のイテレーターの型と逆参照操作中に適用される単項関数の型は、どちらも transform_iterator クラスのテンプレート・パラメーターでなければなりません。transform_iterator クラスは 3 つのコンストラクターを提供します。
transform_iterator(): デフォルトで構築されたベース・イテレーターと単項ファンクターを使用して、イテレーターのインスタンスを作成します。
transform_iterator(iter): 提供されたベース・イテレーターとデフォルトで構築された単項ファンクターを使用して、イテレーターのインスタンスを作成します。
transform_iterator(iter, func): 提供されたベース・イテレーターと単項ファンクターを使用して、イテレーターのインスタンスを作成します。
イテレーターを簡単に構築できるように、oneapi::dpl::make_transform_iterator が提供されています。この関数は、引数としてオリジナルのイテレーターと変換操作のインスタンスを受け取り、transform_iterator インスタンスを構築します。
using namespace oneapi;
dpl::counting_iterator<int> first(0);
dpl::counting_iterator<int> last(10);
auto transform_first = dpl::make_transform_iterator(first, std::negate<int>());
auto transform_last = transform_first + (last - first);
auto sum = std::reduce(dpl::execution::dpcpp_default,
transform_first, transform_last); // sum is (0 + -1 + ...+ -9) = -45
permutation_iterator: 逆参照値のセットが提供されるソース・イテレーターによって定義されるイテレーターで、逆参照値のセットの反復順序は、別のイテレーター、またはインデックス演算子が permutation_iterator インデックスからソース・イテレーターのインデックスへのマップを定義するファンクターのいずれかによって定義されます。permutation_iterator は、イテレーターで表されるデータの非連続要素を、連続しているかのようにアルゴリズムで処理する必要があるアプリケーションを実装するのに役立ちます。一例として、出力イテレーターに 1 つおきに要素をコピーする場合があります。
イテレーター・インスタンスを容易に構築できるように、make_permutation_iterator が提供されています。この関数は、ソース・イテレーターとインデックス・マップを表すイテレーター (関数オブジェクト) を受け取ります。
struct multiply_index_by_two {
template <typename Index>
Index operator()(const Index& i)
{ return i*2; }
};
// 最初と最後は入力要素の連続する範囲を定義するイテレーター
// 置換イテレーターによってアクセスされる、最初と最後の間の
// 範囲内の要素数を計算する
size_t num_elements = std::distance(first, last) / 2 + std::distance(first, last) % 2;
using namespace oneapi;
auto permutation_first = dpl::make_permutation_iterator(first, multiply_index_by_two());
auto permutation_last = permutation_first + num_elements;
std::copy(dpl::execution::dpcpp_default, permutation_first, permutation_last, result);