23 Ranges library [ranges]

23.6 Range utilities [range.utility]

23.6.2 View interface [view.interface]

The class template view_­interface is a helper for defining View-like types that offer a container-like interface.
It is parameterized with the type that is derived from it.
namespace std::ranges {
  template<Range R>
  struct range-common-iterator-impl {                   // exposition only
    using type = common_iterator<iterator_t<R>, sentinel_t<R>>;
  };
  template<CommonRange R>
  struct range-common-iterator-impl<R> {                // exposition only
    using type = iterator_t<R>;
  };
  template<Range R>
    using range-common-iterator =                       // exposition only
      typename range-common-iterator-impl<R>::type;

  template<class D>
    requires is_class_v<D> && Same<D, remove_cv_t<D>>
  class view_interface : public view_base {
  private:
    constexpr D& derived() noexcept {                   // exposition only
      return static_cast<D&>(*this);
    }
    constexpr const D& derived() const noexcept {       // exposition only
      return static_cast<const D&>(*this);
    }
  public:
    constexpr bool empty() requires ForwardRange<D> {
      return ranges::begin(derived()) == ranges::end(derived());
    }
    constexpr bool empty() const requires ForwardRange<const D> {
      return ranges::begin(derived()) == ranges::end(derived());
    }

    constexpr explicit operator bool()
      requires requires { ranges::empty(derived()); } {
        return !ranges::empty(derived());
      }
    constexpr explicit operator bool() const
      requires requires { ranges::empty(derived()); } {
        return !ranges::empty(derived());
      }

    constexpr auto data() requires ContiguousIterator<iterator_t<D>> {
      return ranges::empty(derived()) ? nullptr : addressof(*ranges::begin(derived()));
    }
    constexpr auto data() const
      requires Range<const D> && ContiguousIterator<iterator_t<const D>> {
        return ranges::empty(derived()) ? nullptr : addressof(*ranges::begin(derived()));
      }

    constexpr auto size() requires ForwardRange<D> &&
      SizedSentinel<sentinel_t<D>, iterator_t<D>> {
        return ranges::end(derived()) - ranges::begin(derived());
      }
    constexpr auto size() const requires ForwardRange<const D> &&
      SizedSentinel<sentinel_t<const D>, iterator_t<const D>> {
        return ranges::end(derived()) - ranges::begin(derived());
      }

    constexpr decltype(auto) front() requires ForwardRange<D>;
    constexpr decltype(auto) front() const requires ForwardRange<const D>;

    constexpr decltype(auto) back() requires BidirectionalRange<D> && CommonRange<D>;
    constexpr decltype(auto) back() const
      requires BidirectionalRange<const D> && CommonRange<const D>;

    template<RandomAccessRange R = D>
      constexpr decltype(auto) operator[](iter_difference_t<iterator_t<R>> n) {
        return ranges::begin(derived())[n];
      }
    template<RandomAccessRange R = const D>
      constexpr decltype(auto) operator[](iter_difference_t<iterator_t<R>> n) const {
        return ranges::begin(derived())[n];
      }
  };
}
The template parameter D for view_­interface may be an incomplete type.
Before any member of the resulting specialization of view_­interface other than special member functions is referenced, D shall be complete, and model both DerivedFrom<view_­interface<D>> and View.

23.6.2.1 Members [view.interface.members]

constexpr decltype(auto) front() requires ForwardRange<D>; constexpr decltype(auto) front() const requires ForwardRange<const D>;
Expects: !empty().
Effects: Equivalent to: return *ranges::begin(derived());
constexpr decltype(auto) back() requires BidirectionalRange<D> && CommonRange<D>; constexpr decltype(auto) back() const requires BidirectionalRange<const D> && CommonRange<const D>;
Expects: !empty().
Effects: Equivalent to: return *ranges::prev(ranges::end(derived()));