23 Ranges library [ranges]

23.8 Range adaptors [range.adaptors]

23.8.7 Join view [range.join]

23.8.7.4 Class template join_­view​::​sentinel [range.join.sentinel]

namespace std::ranges {
  template<class V>
  template<bool Const>
  struct join_view<V>::sentinel {
  private:
    using Parent =                                      // exposition only
      conditional_t<Const, const join_view, join_view>;
    using Base   = conditional_t<Const, const V, V>;    // exposition only
    sentinel_t<Base> end_ = sentinel_t<Base>();         // exposition only
  public:
    sentinel() = default;

    constexpr explicit sentinel(Parent& parent);
    constexpr sentinel(sentinel<!Const> s)
      requires Const && ConvertibleTo<sentinel_t<V>, sentinel_t<Base>>;

    friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
    friend constexpr bool operator==(const sentinel& x, const iterator<Const>& y);
    friend constexpr bool operator!=(const iterator<Const>& x, const sentinel& y);
    friend constexpr bool operator!=(const sentinel& x, const iterator<Const>& y);
  };
}
constexpr explicit sentinel(Parent& parent);
Effects: Initializes end_­ with ranges::end(parent.base_­).
constexpr sentinel(sentinel<!Const> s) requires Const && ConvertibleTo<sentinel_t<V>, sentinel_t<Base>>;
Effects: Initializes end_­ with std::move(s.end_­).
friend constexpr bool operator==(const iterator<Const>& x, const sentinel& y);
Effects: Equivalent to: return x.outer_­ == y.end_­;
friend constexpr bool operator==(const sentinel& x, const iterator<Const>& y);
Effects: Equivalent to: return y == x;
friend constexpr bool operator!=(const iterator<Const>& x, const sentinel& y);
Effects: Equivalent to: return !(x == y);
friend constexpr bool operator!=(const sentinel& x, const iterator<Const>& y);
Effects: Equivalent to: return !(y == x);