概要
std::span
は、シーケンスの所有権を保持せず、部分シーケンスを参照するクラスである。
このクラスは、std::vector
や配列といったコンテナから一部の連続的な要素を抽出し、それらの要素にのみなんらかの処理を適用する、という目的に使用できる。
文字列操作に特化したクラスとしてstd::basic_string_view
が定義されているが、こちらはメモリ連続性をもつあらゆるコンテナに適用できる。
このクラスは、トリビアルコピー可能である(C++23)
メモリ連続性
このクラスの対象は、メモリの連続性を持つシーケンスである。例として、以下は対象のシーケンスである:
メモリ連続性をもつクラスは、非メンバ関数data()
によってポインタを取得でき、非メンバ関数size()
によって要素数を取得できること。それらの関数は、ADLによって呼び出される。
静的な要素数と、動的な要素数
std::span
は、静的な要素数をもつ場合と、動的な要素数をもつ場合の両方をサポートする。それはテンプレートパラメータExtent
によって表される。動的な要素数をもつ場合は、Extent
としてstd::dynamic_extent
を指定する。動的な要素数は、std::vector
を参照したり、ポインタと要素数の組を扱ったり、参照範囲を動的に変更したりする場合に必要となる。
静的な要素数をもつ場合、メンバ定数extent
に要素数が保持されるため、メンバ変数として要素数を保持する必要がなく、領域を節約する最適化を行える。
ElementType
は、抽象型ではない完全オブジェクト型であること
備考
std::span
が参照する範囲[s.data(), s.data() + s.size())
に含まれるポインタを無効にする操作を行った場合、std::span
オブジェクトのメンバ関数から返されるその範囲のポインタ、イテレータ、*this
以外の参照が無効になる
メンバ関数
構築・破棄
名前 |
説明 |
対応バージョン |
(constructor) |
コンストラクタ |
C++20 |
~span() = default; |
デストラクタ |
C++20 |
span& operator=(const span&) = default; span& operator=(span&&) = default; |
代入演算子 |
C++20 |
サブシーケンスの参照
名前 |
説明 |
対応バージョン |
first |
先頭N個の要素を参照するspan オブジェクトを取得する |
C++20 |
last |
末尾N個の要素を参照するspan オブジェクトを取得する |
C++20 |
subspan |
任意の位置からN個の要素を参照するspan オブジェクトを取得する |
C++20 |
領域
名前 |
説明 |
対応バージョン |
size |
参照している要素数を取得する |
C++20 |
size_bytes |
参照している範囲のバイト数を取得する |
C++20 |
empty |
参照している範囲が空かどうかを判定する |
C++20 |
要素アクセス
名前 |
説明 |
対応バージョン |
operator[] |
参照範囲から、任意の位置の要素を取得する |
C++20 |
at |
参照範囲から、任意の位置の要素を取得する |
C++26 |
front |
参照範囲の先頭要素を取得する |
C++20 |
back |
参照範囲の末尾要素を取得する |
C++20 |
data |
参照範囲の先頭を指すポインタを取得する |
C++20 |
イテレータ
名前 |
説明 |
対応バージョン |
begin |
先頭要素を指すイテレータを取得する |
C++20 |
end |
末尾要素の次を指すイテレータを取得する |
C++20 |
rbegin |
末尾要素を指す逆順イテレータを取得する |
C++20 |
rend |
先頭要素の前を指す逆順イテレータを取得する |
C++20 |
cbegin |
先頭の要素を指す読み取り専用イテレータを取得する |
C++23 |
cend |
末尾の次を指す読み取り専用イテレータを取得する |
C++23 |
crbegin |
末尾を指す読み取り専用逆イテレータを取得する |
C++23 |
crend |
先頭の前を指す読み取り専用逆イテレータを取得する |
C++23 |
メンバ定数
名前 |
説明 |
対応バージョン |
static constexpr size_type extent = Extent; |
要素数。値が-1 であれば動的な要素数、そうでなければ静的な固定要素数 |
C++20 |
メンバ型
名前 |
説明 |
対応バージョン |
element_type |
要素型 ElementType |
C++20 |
value_type |
CV修飾を除いた要素型 remove_cv_t<ElementType> |
C++20 |
size_type |
インデックスを表す符号なし整数型 size_t |
C++20 |
difference_type |
イテレータの差を表す符号付き整数型 ptrdiff_t |
C++20 |
pointer |
ポインタ型 element_type* |
C++20 |
const_pointer |
const ポインタ型 const element_type* |
C++20 |
reference |
参照型 element_type& |
C++20 |
const_reference |
const 参照型 const element_type& |
C++20 |
iterator |
実装定義のイテレータ型。contiguous_iterator 、random_access_iterator 、constexprイテレータのモデルであり、コンテナのイテレータに対するすべての要件を満たす |
C++20 |
reverse_iterator |
逆順イテレータ reverse_iterator<iterator> |
C++20 |
const_iterator |
読み取り専用イテレータ std::const_iterator<iterator> |
C++23 |
const_reverse_iterator |
読み取り専用逆イテレータ std::const_iterator<reverse_iterator> |
C++23 |
非メンバ関数
オブジェクトのバイト表現
推論補助
例
基本的な使い方
#include <iostream>
#include <span>
#include <vector>
#include <utility>
// メモリ連続性をもつあらゆる範囲を出力する関数。
// std::spanオブジェクトはコピーで受け取るのが基本的な使い方
template <class T, std::size_t Extent>
void print(std::span<T, Extent> s)
{
const char* delimiter = "";
std::cout << '{';
for (const T& x : s) {
std::cout << std::exchange(delimiter, ",") << x;
}
std::cout << '}' << std::endl;
}
int main()
{
std::vector<int> v = {1, 2, 3, 4, 5};
int ar[] = {1, 2, 3, 4, 5};
// spanに変換してコンテナ全体を出力
print(std::span{v});
// コンテナの一部の要素を出力
print(std::span{v}.subspan(1, 3));
// ポインタと要素数を指定した範囲を参照して、
// 範囲for文を使用する
print(std::span<int>{ar, 3});
}
出力
{1,2,3,4,5}
{2,3,4}
{1,2,3}
データのヘッダ情報とボディ情報をコピーなしで分割する
#include <iostream>
#include <span>
#include <vector>
#include <utility>
template <class T>
void process_header(std::span<T> s)
{
const char* delimiter = "";
std::cout << "[header] : ";
for (int x : s) {
std::cout << std::exchange(delimiter, ",") << x;
}
std::cout << std::endl;
}
template <class T>
void process_body(std::span<T> s)
{
const char* delimiter = "";
std::cout << "[body] : ";
for (int x : s) {
std::cout << std::exchange(delimiter, ",") << x;
}
std::cout << std::endl;
}
template <class T>
void f(std::span<T> s)
{
std::size_t header_size = 3;
process_header(s.first(header_size));
process_body(s.last(s.size() - header_size));
}
int main()
{
std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
f(std::span{data});
}
出力
[header] : 1,2,3
[body] : 4,5,6,7,8,9,10
バージョン
言語
処理系
参照