23 Ranges library [ranges]

23.8 Range adaptors [range.adaptors]

23.8.7 Join view [range.join]

23.8.7.2 Class template join_­view [range.join.view]

namespace std::ranges {
  template<InputRange V>
    requires View<V> && InputRange<iter_reference_t<iterator_t<V>>> &&
             (is_reference_v<iter_reference_t<iterator_t<V>>> ||
              View<iter_value_t<iterator_t<V>>>)
  class join_view : public view_interface<join_view<V>> {
  private:
    using InnerRng =                    // exposition only
      iter_reference_t<iterator_t<V>>;
    template<bool Const>
      struct iterator;                  // exposition only
    template<bool Const>
      struct sentinel;                  // exposition only

    V base_ = V();                      // exposition only
    all_view<InnerRng> inner_ =         // exposition only, present only when !is_­reference_­v<InnerRng>
      all_view<InnerRng>();
  public:
    join_view() = default;
    constexpr explicit join_view(V base);

    template<InputRange R>
      requires ViewableRange<R> && Constructible<V, all_view<R>>
    constexpr explicit join_view(R&& r);

    constexpr auto begin() {
      return iterator<simple-view<V>>{*this, ranges::begin(base_)};
    }

    constexpr auto begin() const
    requires InputRange<const V> &&
             is_reference_v<iter_reference_t<iterator_t<const V>>> {
      return iterator<true>{*this, ranges::begin(base_)};
    }

    constexpr auto end() {
      if constexpr (ForwardRange<V> &&
                    is_reference_v<InnerRng> && ForwardRange<InnerRng> &&
                    CommonRange<V> && CommonRange<InnerRng>)
        return iterator<simple-view<V>>{*this, ranges::end(base_)};
      else
        return sentinel<simple-view<V>>{*this};
    }

    constexpr auto end() const
    requires InputRange<const V> &&
             is_reference_v<iter_reference_t<iterator_t<const V>>> {
      if constexpr (ForwardRange<const V> &&
                    is_reference_v<iter_reference_t<iterator_t<const V>>> &&
                    ForwardRange<iter_reference_t<iterator_t<const V>>> &&
                    CommonRange<const V> &&
                    CommonRange<iter_reference_t<iterator_t<const V>>>)
        return iterator<true>{*this, ranges::end(base_)};
      else
        return sentinel<true>{*this};
    }
  };

  template<class R>
    explicit join_view(R&&) -> join_view<all_view<R>>;
}
constexpr explicit join_view(V base);
Effects: Initializes base_­ with std::move(base).
template<InputRange R> requires ViewableRange<R> && Constructible<V, all_view<R>> constexpr explicit join_view(R&& r);
Effects: Initializes base_­ with view::all(std::forward<R>(r)).