namespace std {
template<class FirstType, class LastType, class StrideType = constant_wrapper<1zu>>
struct range_slice {
[[no_unique_address]] FirstType first{};
[[no_unique_address]] LastType last{};
[[no_unique_address]] StrideType stride{};
};
}
概要
range_sliceは、多次元配列の特定次元に対して、取り出し元の半開区間とストライド幅を指定した要素取り出しを指示する集成体クラステンプレートである。
初期化時にメンバ変数名を明記する指示付き初期化をサポートし、テンプレートパラメータはテンプレート引数推論の利用を想定した設計となっている。
first: 取り出し元の半開区間の下限last: 取り出し元の半開区間の上限stride: 要素取り出しストライド幅(省略時は1)
半開区間[first, last)から、firstを起点にstride間隔で要素を取り出す。
// 区間[1, 11)から、ストライド幅3で取り出す
// → インデックス 1, 4, 7, 10 の要素を取り出す
std::range_slice{.first=1, .last=11, .stride=3}
これはPythonのarray[first:last:step]と同じ指定方法である。取り出し元の区間ではなく取り出す要素数で指定したい場合は、extent_sliceを使用する。
適格要件
FirstType, LastType, StrideTypeは符号付き整数型または符号無し整数型、もしくはintegral-constant-likeのモデルであること。
備考
range_sliceは正則submdspanスライス型ではない。canonical_slices()関数によって、等価なextent_slice(要素数はstrideによる除算で求められる)へ変換されたうえでレイアウトマッピングへ渡される- そのため、
strideが実行時の値である場合は、取り出した多次元配列ビューの要素数も実行時の値となる
例
#include <mdspan>
#include <print>
#include <numeric>
int main()
{
// 12要素の1次元配列ビュー
int arr[12];
std::ranges::iota(arr, 0);
std::mdspan vec0{arr};
// 区間[1, 11)から、ストライド幅3で取り出す
auto vec1 = std::submdspan(vec0, std::range_slice{.first=1, .last=11, .stride=3});
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
// ^ . . ^ . . ^ . . ^
std::println("vec1:");
for (size_t i = 0; i < vec1.extent(0); i++) {
std::print(" {}", vec1[i]);
}
// ストライド幅を省略すると、区間内の全要素を取り出す
auto vec2 = std::submdspan(vec0, std::range_slice{2, 6});
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
// ^ ^ ^ ^
std::println("\nvec2:");
for (size_t i = 0; i < vec2.extent(0); i++) {
std::print(" {}", vec2[i]);
}
}
出力
vec1:
1 4 7 10
vec2:
2 3 4 5
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: 17 ✅
- ICC: ??
- Visual C++: ??
関連項目
参照
- P3982R2 Split
strided_sliceintoextent_sliceandrange_slicefor C++26- C++26で、取り出し元の半開区間で指定するスライス指定子としてこのクラスが追加された。ほかのプログラミング言語のスライス指定と同じ記述ができるようにするためである