namespace std::ranges {
template<class T>
concept sized_range = range<T> && requires(T& t) { ranges::size(t); };
}
概要
sized_rangeは、大きさを償却定数時間で求めることができるRangeを表すコンセプトである。
sized_rangeなRangeからはranges::sizeで大きさを取得できる。
sized_rangeではないRangeとしては、iota_viewのように無限長のもの、
forward_listのように大きさは決まっているが償却定数時間で求められないもの、
basic_istream_viewのように事前に求められないものなどがある。
モデル
型がremove_reference_t<T>であるようなlvaluetがあるとする。Tがsized_rangeのモデルとなるのは、以下の条件をすべて満たす場合である。
ranges::size(t)が償却定数時間で実行でき、ranges::distance(t)と等しく、tを変更しない。- もし
iterator_t<T>がforward_iteratorのモデルであれば、ranges::size(t)はranges::begin(t)の評価によらず一意に定まる。
構文要件では、ranges::size(t)という呼び出しが可能であることしか要求されない。これは例えばTのメンバ関数size()が整数を返せば満たしてしまうが、その計算量が償却定数でない場合はsized_rangeのモデルとはならないので、disable_sized_rangeをtrueに特殊化してranges::size(t)を無効化する必要がある。
2番目の要件は、イテレータがinput_iteratorまたはoutput_iteratorであるときは、ranges::beginを呼び出すまでは大きさが定まらない、といった依存関係が許可されることを意味している。
例
#include <ranges>
#include <list>
#include <forward_list>
#include <vector>
int main()
{
// vectorはsized_range
static_assert(std::ranges::sized_range<std::vector<int>>);
// listもsized_range
static_assert(std::ranges::sized_range<std::list<int>>);
// forward_listはsized_rangeではない
static_assert(!std::ranges::sized_range<std::forward_list<int>>);
}
出力
バージョン
言語
- C++20
処理系
- Clang: 13.0.0 ✅
- GCC: 10.1.0 ✅
- ICC: ??
- Visual C++: 2019 Update 10 ✅