namespace std::ranges {
template<class T>
concept range = requires(T& t) {
ranges::begin(t);
ranges::end(t);
};
}
概要
要素の範囲を表すイテレータと番兵を取得でき、それらによって要素をイテレートできる型を表す、Rangeの最も基本的なコンセプト。
モデル
decltype((t))
がT&
であるような式t
があるとする。T
がrange
のモデルとなるのは、以下の条件をすべて満たす場合である。
- [
ranges::begin(t)
,ranges::end(t)
) が範囲を表す。 ranges::begin(t)
とranges::end(t)
は共に償却定数時間で値を返し、Rangeを変更しない。ranges::begin(t)
の型がforward_iterator
のモデルであるならば、ranges::begin(t)
は等しさを保持する。
式が等しさを保持する(equality‑preserving)とは、同じ入力に対しては常に同じ結果となることをいう。
イテレータi
に前置インクリメントを有限回適用したとき、番兵s
と等しくなるならば、s
はi
から到達可能であるという。また、そのとき、[i, s)
は範囲を表す。
1番目の要件では、同じRangeオブジェクトから取得したイテレータと番兵は、同じRangeのイテレータと番兵であることが要求される。特に、有限長のRangeであれば、番兵はイテレータから到達可能でなければならない。 2番目の要件では、要件が償却定数時間であることにより、イテレータを取得するタイミングで初めて要素を生成するような実装が許可される。
備考
forward_iterator
なRangeに対してranges::begin
とranges::end
の両方が等しさを保持するならば、そのRangeを何度もアルゴリズム関数に渡したり、イテレータを繰り返し取得して使ったりしてもよい。
イテレータがforward_iterator
のモデルではない場合は、ranges::begin
でイテレータを繰り返し取得したときに同じオブジェクトが返る保証はなく、結果が一意に定まるともいえない。そのような場合、ranges::begin
の呼び出しはRange1つあたり1回に留めなければならない。
例
#include <ranges>
#include <vector>
int main()
{
static_assert(std::ranges::range<std::vector<int>>);
static_assert(std::ranges::range<int[3]>);
static_assert(!std::ranges::range<double>);
static_assert(!std::ranges::range<const char*>);
static_assert(!std::ranges::range<int[]>);
}
#include <ranges>
#include <vector>
int main()
{
static_assert(std::ranges::range<std::vector<int>>);
static_assert(std::ranges::range<int[3]>);
static_assert(!std::ranges::range<double>);
static_assert(!std::ranges::range<const char*>);
static_assert(!std::ranges::range<int[]>);
}
出力
バージョン
言語
- C++20
処理系
- Clang: 13.0.0 ✅
- GCC: 10.1.0 ✅
- ICC: ??
- Visual C++: 2019 Update 10 ✅