template<class T>
concept borrowed_range =
range<T> && (is_lvalue_reference_v<T> || enable_borrowed_range<remove_cvref_t<T>>);
template<class>
constexpr bool enable_borrowed_range = false;
template<class T>
concept sized_range =
range<T> && requires(T& t) { ranges::size(t); };
template<class>
constexpr bool disable_sized_range = false;
template<class T>
constexpr bool is-derived-from-view-interface = see below; // exposition only
template<class T>
constexpr bool enable_view =
derived_from<T, view_base> || is-derived-from-view-interface<T>;
template<class R, class T>
concept output_range =
range<R> && output_iterator<iterator_t<R>, T>;
template<class T>
concept input_range =
range<T> && input_iterator<iterator_t<T>>;
template<class T>
concept forward_range =
input_range<T> && forward_iterator<iterator_t<T>>;
template<class T>
concept bidirectional_range =
forward_range<T> && bidirectional_iterator<iterator_t<T>>;
template<class T>
concept random_access_range =
bidirectional_range<T> && random_access_iterator<iterator_t<T>>;
template<class T>
concept contiguous_range =
random_access_range<T> && contiguous_iterator<iterator_t<T>> &&
requires(T& t) {
{ ranges::data(t) } -> same_as<add_pointer_t<range_reference_t<T>>>;
};
template<class T>
concept common_range =
range<T> && same_as<iterator_t<T>, sentinel_t<T>>;
template<class R>
constexpr bool is-initializer-list = see below; // exposition only
template<class T>
concept viewable_range =
range<T> &&
((view<remove_cvref_t<T>> && constructible_from<remove_cvref_t<T>, T>) ||
(!view<remove_cvref_t<T>> &&
(is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !is-initializer-list<T>))));
template<class T>
concept constant_range =
input_range<T> && constant-iterator<iterator_t<T>>;