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 ✅