C++20には所有権を持たず範囲を表すクラスとしてstd::span
、std::basic_string_view
、std::ranges::subrange
が用意されています。これらの概要は以下の通りです。
クラス | 概要 |
---|---|
std::span |
連続したメモリ領域の部分を参照する。 |
std::basic_string_view |
文字列とみなせる連続したメモリ領域の部分を参照する。 |
std::ranges::subrange |
イテレーターで先頭と番兵(末尾の次)を指定された範囲を参照する。 |
std::span
std::span
は連続したメモリ領域、具体的には生の配列、std::array
、std::basic_string
、std::vector
等の部分を参照できます。std::list
のような連続しないメモリではコンパイルエラーが発生します。
#include <list> #include <span> #include <vector> int main() { // std::vectorはメモリ連続なのでstd::span作成可能 std::vector<int> vec{ 0, 1, 2, 3, 4 }; auto vec_span = std::span(vec); auto vec_subspan = vec_span.subspan(1, 2); // vec_span: {0, 1, 2, 3, 4} // vec_subspan: {1, 2} // std::listはメモリ連続ではないのでstd::span作成不可能 std::list<int> list{ 0, 1, 2, 3, 4 }; // std::span list_span{ list }; return 0; }
std::basic_string_view
std::basic_string_view
はstd::span
の文字列版です。std::basic_string_view
自体が文字列操作関数(starts_with
等)を持ち、またstd::basic_string_view
へのキャストを定義することであるクラスが文字列であることを表現できます。
std::ranges::subrange
std::ranges::subrange
は先頭と番兵(末尾の次)のイテレーターとして受け取り、その間[先頭、番兵)を参照できます。要素の列挙はイテレーターの操作により実行されるため、メモリが連続である必要も反復回数が固定や有限である必要もありません。
#include <list> #include <ranges> #include <vector> int main() { std::vector<int> vec{ 0, 1, 2, 3, 4 }; std::ranges::subrange vec_all( vec.cbegin(), vec.cend()); std::ranges::subrange vec_part( std::next(vec.begin(), 1), std::next(vec.begin(), 3)); // vec_all: {0, 1, 2, 3, 4} // vec_part: {1, 2} std::list<int> list{ 0, 1, 2, 3, 4 }; std::ranges::subrange list_all( list.cbegin(), list.cend()); std::ranges::subrange list_part( std::next(list.begin(), 1), std::next(list.begin(), 3)); // list_all: {0, 1, 2, 3, 4} // list_part: {1, 2} }
subrange
はrange
コンセプトを満たすため、rangesビュー(std::views
)の処理を適用できます。結果は処理に対応するビューです。
#include <iostream> #include <list> #include <ranges> int main() { std::list<int> list{ 0, 1, 2, 3, 4 }; std::ranges::subrange list_all(list.cbegin(), list.cend()); auto list_part = list_all | std::views::drop(2) | std::views::take(2); for (const auto& elem : list_part) std::wcout << elem << std::endl; // 2, 3 }
std::span
やstd::basic_string_view
もrange
コンセプトを満たすのでrangesビュー(std::views
)の処理を適用できます。ただし、結果はstd::span
やstd::basic_string_view
ではなく、処理に対応するビューです。