template<class R, class T>
concept OutputRange =
Range<R> && OutputIterator<iterator_t<R>, T>;
template<class T>
concept InputRange =
Range<T> && InputIterator<iterator_t<T>>;
template<class T>
concept ForwardRange =
InputRange<T> && ForwardIterator<iterator_t<T>>;
template<class T>
concept BidirectionalRange =
ForwardRange<T> && BidirectionalIterator<iterator_t<T>>;
template<class T>
concept RandomAccessRange =
BidirectionalRange<T> && RandomAccessIterator<iterator_t<T>>;
template<class T>
concept ContiguousRange =
RandomAccessRange<T> && ContiguousIterator<iterator_t<T>> &&
requires(T& t) {
{ ranges::data(t) } -> Same<add_pointer_t<iter_reference_t<iterator_t<T>>>>;
};
template<class T>
concept CommonRange =
Range<T> && Same<iterator_t<T>, sentinel_t<T>>;
template<class T>
concept ViewableRange =
Range<T> && (forwarding-range<T> || View<decay_t<T>>);