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>>;