}
        constexpr auto cend() const requires range<const D> {
          return [ranges::cend](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/cend)(derived());
        }
     
        constexpr explicit operator bool()
          requires requires { [ranges::empty](http://en.cppreference.com/w/cpp/ranges/empty)(derived()); } {
            return ![ranges::empty](http://en.cppreference.com/w/cpp/ranges/empty)(derived());
          }
        constexpr explicit operator bool() const
          requires requires { [ranges::empty](http://en.cppreference.com/w/cpp/ranges/empty)(derived()); } {
            return ![ranges::empty](http://en.cppreference.com/w/cpp/ranges/empty)(derived());
          }
     
        constexpr auto data() requires contiguous_iterator<iterator_t<D>> {
          return to_address([ranges::begin](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin)(derived()));
        }
        constexpr auto data() const
          requires range<const D> && contiguous_iterator<iterator_t<const D>> {
            return to_address([ranges::begin](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin)(derived()));
          }
     
        constexpr auto size() requires forward_range<D> &&
          sized_sentinel_for<sentinel_t<D>, iterator_t<D>> {
            return [ranges::end](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/end)(derived()) - [ranges::begin](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin)(derived());
          }
        constexpr auto size() const requires forward_range<const D> &&
          sized_sentinel_for<sentinel_t<const D>, iterator_t<const D>> {
            return [ranges::end](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/end)(derived()) - [ranges::begin](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin)(derived());
          }
     
        constexpr decltype(auto) front() requires forward_range<D>;
        constexpr decltype(auto) front() const requires forward_range<const D>;
     
        constexpr decltype(auto) back() requires bidirectional_range<D> && common_range<D>;
        constexpr decltype(auto) back() const
          requires bidirectional_range<const D> && common_range<const D>;
     
        template<random_access_range R = D>
          constexpr decltype(auto) operator[](range_difference_t<R> n) {
            return [ranges::begin](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin)(derived())[n];
          }
        template<random_access_range R = const D>
          constexpr decltype(auto) operator[](range_difference_t<R> n) const {
            return [ranges::begin](http://en.cppreference.com/w/cpp/ranges-ranges-placeholder/begin)(derived())[n];
          }
      };
    }

####  [ [ edit
](/mwiki/index.php?title=Template:cpp/synopsis/ranges&action=edit&section=T-15
"Template:cpp/synopsis/ranges") ]  Class template  [ std::ranges::subrange
](/w/cpp/ranges/subrange "cpp/ranges/subrange")

    
    
    namespace std::ranges {
      template<class From, class To>
        concept __uses_nonqualification_pointer_conversion =      // exposition only
          is_pointer_v<From> && is_pointer_v<To> &&
          !convertible_to<remove_pointer_t<From>(*)[], remove_pointer_t<To>(*)[]>;
     
      template<class From, class To>
        concept __convertible_to_non_slicing =                    // exposition only
          convertible_to<From, To> &&
          !__uses_nonqualification_pointer_conversion<decay_t<From>, decay_t<To>>;
     
      template<class T, class U, class V>
        concept __pair_like_convertible_from =                    // exposition only
          !range<T> && !is_reference_v<T> && __pair_like<T> &&
          constructible_from<T, U, V> &&
          __convertible_to_non_slicing<U, tuple_element_t<0, T>> &&
          convertible_to<V, tuple_element_t<1, T>>;
     
      template<input_or_output_iterator I, sentinel_for<I> S = I, subrange_kind K =
          s