// -*- C++ -*-
// C++23 overlay for <ranges>
// Adds: views::enumerate, views::chunk, views::slide
//       ranges::fold_left, ranges::fold_right, ranges::fold_left_first
//
// Wraps the system <ranges> and injects missing C++23 features.
// Uses std::ranges::range_adaptor_closure for proper pipe (|) support.

#ifndef _OMNI_CPP23_RANGES_OVERLAY
#define _OMNI_CPP23_RANGES_OVERLAY

// Pull in the system <ranges> first
#include_next <ranges>

#include <tuple>
#include <type_traits>
#include <optional>
#include <functional>

#if __cplusplus >= 202100L

// ─── Feature-test macros ─────────────────────────────────────────────────────
#ifndef __cpp_lib_ranges_enumerate
#define __cpp_lib_ranges_enumerate 202302L
#endif
#ifndef __cpp_lib_ranges_chunk
#define __cpp_lib_ranges_chunk 202202L
#endif
#ifndef __cpp_lib_ranges_slide
#define __cpp_lib_ranges_slide 202202L
#endif
#ifndef __cpp_lib_ranges_fold
#define __cpp_lib_ranges_fold 202207L
#endif
#ifndef __cpp_lib_ranges_stride
#define __cpp_lib_ranges_stride 202202L
#endif
#ifndef __cpp_lib_ranges_cartesian_product
#define __cpp_lib_ranges_cartesian_product 202207L
#endif
#ifndef __cpp_lib_ranges_join_with
#define __cpp_lib_ranges_join_with 202202L
#endif
#ifndef __cpp_lib_ranges_as_const
#define __cpp_lib_ranges_as_const 202207L
#endif

namespace std::ranges {

// ═══════════════════════════════════════════════════════════════════════════════
// enumerate_view  (P2164R9)
// ═══════════════════════════════════════════════════════════════════════════════

template <input_range _View>
  requires view<_View>
class enumerate_view : public view_interface<enumerate_view<_View>> {
  _View base_ = _View();

  template <bool Const>
  class __iterator {
    using Base = std::conditional_t<Const, const _View, _View>;
    using BaseIter = iterator_t<Base>;

  public:
    using difference_type = range_difference_t<Base>;
    using value_type = std::tuple<difference_type, range_value_t<Base>>;
    using reference = std::tuple<difference_type, range_reference_t<Base>>;
    using iterator_category = std::input_iterator_tag;
    using iterator_concept =
      std::conditional_t<random_access_range<Base>, std::random_access_iterator_tag,
      std::conditional_t<bidirectional_range<Base>, std::bidirectional_iterator_tag,
      std::conditional_t<forward_range<Base>, std::forward_iterator_tag,
        std::input_iterator_tag>>>;

  private:
    BaseIter current_ = BaseIter();
    difference_type pos_ = 0;

  public:
    __iterator() = default;
    constexpr __iterator(BaseIter current, difference_type pos)
      : current_(std::move(current)), pos_(pos) {}

    constexpr reference operator*() const { return reference(pos_, *current_); }

    constexpr __iterator& operator++() { ++current_; ++pos_; return *this; }
    constexpr void operator++(int) { ++*this; }
    constexpr __iterator operator++(int) requires forward_range<Base> {
      auto tmp = *this; ++*this; return tmp;
    }

    constexpr __iterator& operator--() requires bidirectional_range<Base> {
      --current_; --pos_; return *this;
    }
    constexpr __iterator operator--(int) requires bidirectional_range<Base> {
      auto tmp = *this; --*this; return tmp;
    }

    constexpr __iterator& operator+=(difference_type n) requires random_access_range<Base> {
      current_ += n; pos_ += n; return *this;
    }
    constexpr __iterator& operator-=(difference_type n) requires random_access_range<Base> {
      current_ -= n; pos_ -= n; return *this;
    }
    constexpr reference operator[](difference_type n) const requires random_access_range<Base> {
      return reference(pos_ + n, current_[n]);
    }

    friend constexpr bool operator==(const __iterator& x, const __iterator& y) {
      return x.current_ == y.current_;
    }
    friend constexpr auto operator<=>(const __iterator& x, const __iterator& y)
      requires random_access_range<Base> && std::three_way_comparable<BaseIter> {
      return x.current_ <=> y.current_;
    }
    friend constexpr __iterator operator+(__iterator it, difference_type n)
      requires random_access_range<Base> { it += n; return it; }
    friend constexpr __iterator operator+(difference_type n, __iterator it)
      requires random_access_range<Base> { it += n; return it; }
    friend constexpr __iterator operator-(__iterator it, difference_type n)
      requires random_access_range<Base> { it -= n; return it; }
    friend constexpr difference_type operator-(const __iterator& x, const __iterator& y)
      requires random_access_range<Base> { return x.current_ - y.current_; }

    constexpr const BaseIter& base() const& { return current_; }
    constexpr BaseIter base() && { return std::move(current_); }
    constexpr difference_type index() const { return pos_; }
  };

  template <bool Const>
  class __sentinel {
    using Base = std::conditional_t<Const, const _View, _View>;
    sentinel_t<Base> end_ = sentinel_t<Base>();
  public:
    __sentinel() = default;
    constexpr explicit __sentinel(sentinel_t<Base> end) : end_(std::move(end)) {}
    friend constexpr bool operator==(const __iterator<Const>& it, const __sentinel& s) {
      return it.base() == s.end_;
    }
  };

public:
  enumerate_view() requires std::default_initializable<_View> = default;
  constexpr explicit enumerate_view(_View base) : base_(std::move(base)) {}

  constexpr auto begin() { return __iterator<false>(ranges::begin(base_), 0); }
  constexpr auto begin() const requires range<const _View> {
    return __iterator<true>(ranges::begin(base_), 0);
  }
  constexpr auto end() {
    if constexpr (common_range<_View> && sized_range<_View>)
      return __iterator<false>(ranges::end(base_),
        static_cast<range_difference_t<_View>>(ranges::size(base_)));
    else
      return __sentinel<false>(ranges::end(base_));
  }
  constexpr auto end() const requires range<const _View> {
    if constexpr (common_range<const _View> && sized_range<const _View>)
      return __iterator<true>(ranges::end(base_),
        static_cast<range_difference_t<const _View>>(ranges::size(base_)));
    else
      return __sentinel<true>(ranges::end(base_));
  }
  constexpr auto size() requires sized_range<_View> { return ranges::size(base_); }
  constexpr auto size() const requires sized_range<const _View> { return ranges::size(base_); }
  constexpr _View base() const& requires std::copy_constructible<_View> { return base_; }
  constexpr _View base() && { return std::move(base_); }
};

template <class R>
enumerate_view(R&&) -> enumerate_view<views::all_t<R>>;

// ═══════════════════════════════════════════════════════════════════════════════
// chunk_view  (P2442R1) — simplified forward-only implementation
// ═══════════════════════════════════════════════════════════════════════════════

template <forward_range _View>
  requires view<_View>
class chunk_view : public view_interface<chunk_view<_View>> {
  _View base_ = _View();
  range_difference_t<_View> n_ = 1;

public:
  class __iterator {
    using Base = _View;
    using BaseIter = iterator_t<Base>;
  public:
    using difference_type = range_difference_t<Base>;
    using value_type = decltype(views::take(
        subrange(std::declval<BaseIter>(), std::declval<sentinel_t<Base>>()), 0));
    using iterator_concept = std::forward_iterator_tag;

  private:
    BaseIter current_ = BaseIter();
    sentinel_t<Base> end_ = sentinel_t<Base>();
    difference_type n_ = 0;

    constexpr void advance_to_next() {
      ranges::advance(current_, n_, end_);
    }

  public:
    __iterator() = default;
    constexpr __iterator(BaseIter begin, sentinel_t<Base> end, difference_type n)
      : current_(std::move(begin)), end_(std::move(end)), n_(n) {}

    constexpr auto operator*() const {
      auto tail = current_;
      ranges::advance(tail, n_, end_);
      return subrange(current_, tail);
    }

    constexpr __iterator& operator++() {
      advance_to_next();
      return *this;
    }
    constexpr __iterator operator++(int) {
      auto tmp = *this; ++*this; return tmp;
    }

    friend constexpr bool operator==(const __iterator& x, const __iterator& y) {
      return x.current_ == y.current_;
    }
    friend constexpr bool operator==(const __iterator& x, std::default_sentinel_t) {
      return x.current_ == x.end_;
    }

    constexpr BaseIter base() const { return current_; }
  };

  chunk_view() requires std::default_initializable<_View> = default;
  constexpr explicit chunk_view(_View base, range_difference_t<_View> n)
    : base_(std::move(base)), n_(n) {}

  constexpr auto begin() {
    return __iterator(ranges::begin(base_), ranges::end(base_), n_);
  }
  constexpr auto end() {
    return __iterator(ranges::end(base_), ranges::end(base_), n_);
  }
  constexpr _View base() const& requires std::copy_constructible<_View> { return base_; }
  constexpr _View base() && { return std::move(base_); }
};

template <class R>
chunk_view(R&&, range_difference_t<views::all_t<R>>) -> chunk_view<views::all_t<R>>;

// ═══════════════════════════════════════════════════════════════════════════════
// slide_view  (P2442R1)
// ═══════════════════════════════════════════════════════════════════════════════

template <forward_range _View>
  requires view<_View>
class slide_view : public view_interface<slide_view<_View>> {
  _View base_ = _View();
  range_difference_t<_View> n_ = 1;

public:
  class __iterator {
    using Base = _View;
    using BaseIter = iterator_t<Base>;
  public:
    using difference_type = range_difference_t<Base>;
    using value_type = decltype(subrange(
        std::declval<BaseIter>(), std::declval<BaseIter>()));
    using iterator_concept =
      std::conditional_t<random_access_range<Base>, std::random_access_iterator_tag,
      std::conditional_t<bidirectional_range<Base>, std::bidirectional_iterator_tag,
        std::forward_iterator_tag>>;

  private:
    BaseIter current_ = BaseIter();
    BaseIter window_end_ = BaseIter();
    difference_type n_ = 0;

  public:
    __iterator() = default;
    constexpr __iterator(BaseIter current, BaseIter window_end, difference_type n)
      : current_(current), window_end_(window_end), n_(n) {}

    constexpr auto operator*() const {
      return subrange(current_, window_end_);
    }

    constexpr __iterator& operator++() {
      ++current_; ++window_end_;
      return *this;
    }
    constexpr __iterator operator++(int) { auto tmp = *this; ++*this; return tmp; }

    constexpr __iterator& operator--() requires bidirectional_range<Base> {
      --current_; --window_end_;
      return *this;
    }
    constexpr __iterator operator--(int) requires bidirectional_range<Base> {
      auto tmp = *this; --*this; return tmp;
    }

    friend constexpr bool operator==(const __iterator& x, const __iterator& y) {
      return x.current_ == y.current_;
    }

    constexpr BaseIter base() const { return current_; }
  };

  slide_view() requires std::default_initializable<_View> = default;
  constexpr explicit slide_view(_View base, range_difference_t<_View> n)
    : base_(std::move(base)), n_(n) {}

  constexpr auto begin() {
    auto it = ranges::begin(base_);
    auto win = it;
    ranges::advance(win, n_, ranges::end(base_));
    return __iterator(it, win, n_);
  }
  constexpr auto end() {
    // The last valid window starts at position (size - n).
    // So end iterator has current_ at (size - n + 1), i.e. we advance
    // backward from end by (n - 1).
    auto e = ranges::end(base_);
    auto last_start = e;
    ranges::advance(last_start, -(n_ - 1), ranges::begin(base_));
    return __iterator(last_start, e, n_);
  }
  constexpr _View base() const& requires std::copy_constructible<_View> { return base_; }
  constexpr _View base() && { return std::move(base_); }
};

template <class R>
slide_view(R&&, range_difference_t<views::all_t<R>>) -> slide_view<views::all_t<R>>;

// ═══════════════════════════════════════════════════════════════════════════════
// stride_view  (P1899R3) - Takes every Nth element
// ═══════════════════════════════════════════════════════════════════════════════

template <forward_range _View>
  requires view<_View>
class stride_view : public view_interface<stride_view<_View>> {
  _View base_ = _View();
  range_difference_t<_View> n_ = 1;

public:
  class __iterator {
    using Base = _View;
    using BaseIter = iterator_t<Base>;
  public:
    using difference_type = range_difference_t<Base>;
    using value_type = range_value_t<Base>;
    using reference = range_reference_t<Base>;
    using iterator_concept =
      std::conditional_t<random_access_range<Base>, std::random_access_iterator_tag,
      std::conditional_t<bidirectional_range<Base>, std::bidirectional_iterator_tag,
        std::forward_iterator_tag>>;

  private:
    BaseIter current_ = BaseIter();
    sentinel_t<Base> end_ = sentinel_t<Base>();
    difference_type stride_ = 1;

  public:
    __iterator() = default;
    constexpr __iterator(BaseIter current, sentinel_t<Base> end, difference_type stride)
      : current_(std::move(current)), end_(std::move(end)), stride_(stride) {}

    constexpr reference operator*() const { return *current_; }

    constexpr __iterator& operator++() {
      ranges::advance(current_, stride_, end_);
      return *this;
    }
    constexpr __iterator operator++(int) {
      auto tmp = *this; ++*this; return tmp;
    }

    constexpr __iterator& operator--() requires bidirectional_range<Base> {
      ranges::advance(current_, -stride_, ranges::begin(std::declval<Base&>()));
      return *this;
    }
    constexpr __iterator operator--(int) requires bidirectional_range<Base> {
      auto tmp = *this; --*this; return tmp;
    }

    friend constexpr bool operator==(const __iterator& x, const __iterator& y) {
      return x.current_ == y.current_;
    }
    friend constexpr bool operator==(const __iterator& x, std::default_sentinel_t) {
      return x.current_ == x.end_;
    }

    constexpr BaseIter base() const { return current_; }
  };

  stride_view() requires std::default_initializable<_View> = default;
  constexpr explicit stride_view(_View base, range_difference_t<_View> n)
    : base_(std::move(base)), n_(n) {}

  constexpr auto begin() {
    return __iterator(ranges::begin(base_), ranges::end(base_), n_);
  }
  constexpr auto end() {
    return std::default_sentinel;
  }
  constexpr _View base() const& requires std::copy_constructible<_View> { return base_; }
  constexpr _View base() && { return std::move(base_); }
};

template <class R>
stride_view(R&&, range_difference_t<views::all_t<R>>) -> stride_view<views::all_t<R>>;

// ═══════════════════════════════════════════════════════════════════════════════
// cartesian_product_view  (P2374R4) - Simplified 2-range version
// ═══════════════════════════════════════════════════════════════════════════════

template <input_range V1, input_range V2>
  requires view<V1> && view<V2>
class cartesian_product_view : public view_interface<cartesian_product_view<V1, V2>> {
  V1 base1_ = V1();
  V2 base2_ = V2();

public:
  class __iterator {
  private:
    iterator_t<V1> current1_ = iterator_t<V1>();
    sentinel_t<V1> end1_ = sentinel_t<V1>();
    iterator_t<V2> current2_ = iterator_t<V2>();
    sentinel_t<V2> end2_ = sentinel_t<V2>();
    iterator_t<V2> begin2_ = iterator_t<V2>();

  public:
    using difference_type = std::ptrdiff_t;
    using value_type = std::tuple<range_value_t<V1>, range_value_t<V2>>;
    using reference = std::tuple<range_reference_t<V1>, range_reference_t<V2>>;
    using iterator_concept = std::input_iterator_tag;

    __iterator() = default;
    constexpr __iterator(iterator_t<V1> it1, sentinel_t<V1> end1,
                        iterator_t<V2> begin2, iterator_t<V2> it2, sentinel_t<V2> end2)
      : current1_(std::move(it1)), end1_(std::move(end1)),
        current2_(std::move(it2)), end2_(std::move(end2)), begin2_(std::move(begin2)) {}

    constexpr reference operator*() const {
      return reference(*current1_, *current2_);
    }

    constexpr __iterator& operator++() {
      ++current2_;
      if (current2_ == end2_) {
        ++current1_;
        current2_ = begin2_;
      }
      return *this;
    }
    constexpr __iterator operator++(int) {
      auto tmp = *this; ++*this; return tmp;
    }

    friend constexpr bool operator==(const __iterator& x, const __iterator& y) {
      return x.current1_ == y.current1_ && x.current2_ == y.current2_;
    }
    friend constexpr bool operator==(const __iterator& x, std::default_sentinel_t) {
      return x.current1_ == x.end1_;
    }
  };

  cartesian_product_view() requires std::default_initializable<V1> && std::default_initializable<V2> = default;
  constexpr explicit cartesian_product_view(V1 base1, V2 base2)
    : base1_(std::move(base1)), base2_(std::move(base2)) {}

  constexpr auto begin() {
    return __iterator(ranges::begin(base1_), ranges::end(base1_),
                     ranges::begin(base2_), ranges::begin(base2_), ranges::end(base2_));
  }
  constexpr auto end() {
    return std::default_sentinel;
  }
  constexpr V1 base() const& requires std::copy_constructible<V1> { return base1_; }
  constexpr V1 base() && { return std::move(base1_); }
};

template <class R1, class R2>
cartesian_product_view(R1&&, R2&&) -> cartesian_product_view<views::all_t<R1>, views::all_t<R2>>;

// ═══════════════════════════════════════════════════════════════════════════════
// join_with_view  (P2441R2) - Simplified version
// ═══════════════════════════════════════════════════════════════════════════════

template <input_range V, class Pattern>
  requires view<V> && input_range<range_reference_t<V>>
class join_with_view : public view_interface<join_with_view<V, Pattern>> {
  V base_ = V();
  Pattern pattern_ = Pattern();

public:
  class __iterator {
    friend class join_with_view;
    iterator_t<V> outer_it_ = iterator_t<V>();
    sentinel_t<V> outer_end_ = sentinel_t<V>();
    iterator_t<range_reference_t<V>> inner_it_{};
    Pattern* pattern_ptr_ = nullptr;
    iterator_t<Pattern> pattern_it_{};
    iterator_t<Pattern> pattern_end_{};
    bool use_pattern_ = false;
    bool done_ = true;

  public:
    using difference_type = std::ptrdiff_t;
    using value_type = range_value_t<range_reference_t<V>>;
    using inner_reference = range_reference_t<range_reference_t<V>>;
    using pattern_reference = range_reference_t<Pattern>;
    using reference = std::common_reference_t<inner_reference, pattern_reference>;
    using iterator_concept = std::input_iterator_tag;

    __iterator() = default;
    constexpr __iterator(iterator_t<V> outer, sentinel_t<V> outer_end,
                        Pattern* pat)
      : outer_it_(std::move(outer)), outer_end_(std::move(outer_end)),
        pattern_ptr_(pat), done_(false) {
      if (outer_it_ != outer_end_) {
        inner_it_ = ranges::begin(*outer_it_);
        pattern_it_ = ranges::begin(*pattern_ptr_);
        pattern_end_ = ranges::end(*pattern_ptr_);
      } else {
        done_ = true;
      }
    }

    constexpr reference operator*() const {
      if (use_pattern_)
        return *pattern_it_;
      return *inner_it_;
    }

    constexpr __iterator& operator++() {
      if (use_pattern_) {
        ++pattern_it_;
        if (pattern_it_ == pattern_end_) {
          use_pattern_ = false;
          // Move to next inner range
          inner_it_ = ranges::begin(*outer_it_);
        }
      } else {
        ++inner_it_;
        if (inner_it_ == ranges::end(*outer_it_)) {
          ++outer_it_;
          if (outer_it_ != outer_end_) {
            // Switch to pattern before next inner range
            use_pattern_ = true;
            pattern_it_ = ranges::begin(*pattern_ptr_);
            pattern_end_ = ranges::end(*pattern_ptr_);
          } else {
            done_ = true;
          }
        }
      }
      return *this;
    }
    constexpr __iterator operator++(int) {
      auto tmp = *this; ++*this; return tmp;
    }

    friend constexpr bool operator==(const __iterator& x, std::default_sentinel_t) {
      return x.done_;
    }
  };

  join_with_view() requires std::default_initializable<V> && std::default_initializable<Pattern> = default;
  constexpr explicit join_with_view(V base, Pattern pattern)
    : base_(std::move(base)), pattern_(std::move(pattern)) {}

  constexpr auto begin() {
    return __iterator(ranges::begin(base_), ranges::end(base_), &pattern_);
  }
  constexpr auto end() {
    return std::default_sentinel;
  }
  constexpr V base() const& requires std::copy_constructible<V> { return base_; }
  constexpr V base() && { return std::move(base_); }
};

template <class R, class P>
join_with_view(R&&, P&&) -> join_with_view<views::all_t<R>, views::all_t<P>>;

// ═══════════════════════════════════════════════════════════════════════════════
// as_const_view  (P2278R4) - Wraps a view so references are const
// ═══════════════════════════════════════════════════════════════════════════════

template <input_range V>
  requires view<V>
class as_const_view : public view_interface<as_const_view<V>> {
  V base_ = V();

public:
  class __iterator {
  private:
    iterator_t<V> current_ = iterator_t<V>();

  public:
    using difference_type = range_difference_t<V>;
    using value_type = std::remove_cvref_t<range_reference_t<V>>;
    using reference = const std::remove_reference_t<range_reference_t<V>>&;
    using iterator_concept =
      std::conditional_t<random_access_range<V>, std::random_access_iterator_tag,
      std::conditional_t<bidirectional_range<V>, std::bidirectional_iterator_tag,
      std::conditional_t<forward_range<V>, std::forward_iterator_tag,
        std::input_iterator_tag>>>;

    __iterator() = default;
    constexpr explicit __iterator(iterator_t<V> current) : current_(std::move(current)) {}

    constexpr reference operator*() const {
      return static_cast<reference>(*current_);
    }

    constexpr __iterator& operator++() { ++current_; return *this; }
    constexpr __iterator operator++(int) requires forward_range<V> {
      auto tmp = *this; ++*this; return tmp;
    }
    constexpr void operator++(int) { ++*this; }

    constexpr __iterator& operator--() requires bidirectional_range<V> {
      --current_; return *this;
    }
    constexpr __iterator operator--(int) requires bidirectional_range<V> {
      auto tmp = *this; --*this; return tmp;
    }

    friend constexpr bool operator==(const __iterator& x, const __iterator& y) {
      return x.current_ == y.current_;
    }

    constexpr iterator_t<V> base() const { return current_; }
  };

  as_const_view() requires std::default_initializable<V> = default;
  constexpr explicit as_const_view(V base) : base_(std::move(base)) {}

  class __sentinel {
    sentinel_t<V> end_ = sentinel_t<V>();
  public:
    __sentinel() = default;
    constexpr explicit __sentinel(sentinel_t<V> end) : end_(std::move(end)) {}
    friend constexpr bool operator==(const __iterator& it, const __sentinel& s) {
      return it.base() == s.end_;
    }
  };

  constexpr auto begin() {
    return __iterator(ranges::begin(base_));
  }
  constexpr auto begin() const requires range<const V> {
    return __iterator(ranges::begin(base_));
  }
  constexpr auto end() {
    if constexpr (common_range<V>)
      return __iterator(ranges::end(base_));
    else
      return __sentinel(ranges::end(base_));
  }
  constexpr auto end() const requires range<const V> {
    if constexpr (common_range<const V>)
      return __iterator(ranges::end(base_));
    else
      return __sentinel(ranges::end(base_));
  }
  constexpr V base() const& requires std::copy_constructible<V> { return base_; }
  constexpr V base() && { return std::move(base_); }
};

template <class R>
as_const_view(R&&) -> as_const_view<views::all_t<R>>;

// ═══════════════════════════════════════════════════════════════════════════════
// ranges::fold_left / fold_right / fold_left_first  (P2322R6)
// Only defined if not already provided by the system headers.
// ═══════════════════════════════════════════════════════════════════════════════

#if !__has_include(<__algorithm/ranges_fold.h>)
// Guard: Only define if the system libc++ doesn't already provide fold_left.
// Apple's SDK (Xcode 17+) has fold_left in <__algorithm/ranges_fold.h>.
// WASI SDK libc++ does not, so we provide our own implementation.

struct __omni_fold_left_fn {
  template <input_range R, class T, class F>
    requires std::invocable<F&, T, range_reference_t<R>>
  constexpr auto operator()(R&& r, T init, F f) const {
    for (auto it = ranges::begin(r); it != ranges::end(r); ++it)
      init = std::invoke(f, std::move(init), *it);
    return init;
  }
};
inline constexpr __omni_fold_left_fn fold_left{};

struct __omni_fold_left_first_fn {
  template <input_range R, class F>
  constexpr auto operator()(R&& r, F f) const -> std::optional<range_value_t<R>> {
    auto it = ranges::begin(r);
    auto end = ranges::end(r);
    if (it == end) return std::nullopt;
    range_value_t<R> init = *it;
    for (++it; it != end; ++it)
      init = std::invoke(f, std::move(init), *it);
    return std::optional<range_value_t<R>>(std::move(init));
  }
};
inline constexpr __omni_fold_left_first_fn fold_left_first{};

struct __omni_fold_right_fn {
  template <bidirectional_range R, class T, class F>
  constexpr auto operator()(R&& r, T init, F f) const {
    auto it = ranges::end(r);
    auto begin = ranges::begin(r);
    while (it != begin) {
      --it;
      init = std::invoke(f, *it, std::move(init));
    }
    return init;
  }
};
inline constexpr __omni_fold_right_fn fold_right{};

#endif // fold guards

} // namespace std::ranges

// ═══════════════════════════════════════════════════════════════════════════════
// Range adaptor closure objects using range_adaptor_closure (for pipe support)
// ═══════════════════════════════════════════════════════════════════════════════

namespace std::ranges::views {

// ─── enumerate (no arguments → is itself a closure) ──────────────────────────
struct __enumerate_adaptor
  : std::ranges::range_adaptor_closure<__enumerate_adaptor> {
  template <viewable_range R>
  constexpr auto operator()(R&& r) const {
    return enumerate_view(std::forward<R>(r));
  }
};
inline constexpr __enumerate_adaptor enumerate{};

// ─── chunk(n) → returns a closure ───────────────────────────────────────────
template <class D>
struct __chunk_closure : std::ranges::range_adaptor_closure<__chunk_closure<D>> {
  D n_;
  constexpr explicit __chunk_closure(D n) : n_(n) {}
  template <viewable_range R>
  constexpr auto operator()(R&& r) const {
    return chunk_view(std::forward<R>(r),
      static_cast<range_difference_t<views::all_t<R>>>(n_));
  }
};

struct __chunk_adaptor {
  template <viewable_range R>
  constexpr auto operator()(R&& r, auto n) const {
    return chunk_view(std::forward<R>(r),
      static_cast<range_difference_t<views::all_t<R>>>(n));
  }
  constexpr auto operator()(auto n) const {
    return __chunk_closure<decltype(n)>(n);
  }
};
inline constexpr __chunk_adaptor chunk{};

// ─── slide(n) → returns a closure ───────────────────────────────────────────
template <class D>
struct __slide_closure : std::ranges::range_adaptor_closure<__slide_closure<D>> {
  D n_;
  constexpr explicit __slide_closure(D n) : n_(n) {}
  template <viewable_range R>
  constexpr auto operator()(R&& r) const {
    return slide_view(std::forward<R>(r),
      static_cast<range_difference_t<views::all_t<R>>>(n_));
  }
};

struct __slide_adaptor {
  template <viewable_range R>
  constexpr auto operator()(R&& r, auto n) const {
    return slide_view(std::forward<R>(r),
      static_cast<range_difference_t<views::all_t<R>>>(n));
  }
  constexpr auto operator()(auto n) const {
    return __slide_closure<decltype(n)>(n);
  }
};
inline constexpr __slide_adaptor slide{};

// ─── stride(n) → returns a closure ──────────────────────────────────────────
template <class D>
struct __stride_closure : std::ranges::range_adaptor_closure<__stride_closure<D>> {
  D n_;
  constexpr explicit __stride_closure(D n) : n_(n) {}
  template <viewable_range R>
  constexpr auto operator()(R&& r) const {
    return stride_view(std::forward<R>(r),
      static_cast<range_difference_t<views::all_t<R>>>(n_));
  }
};

struct __stride_adaptor {
  template <viewable_range R>
  constexpr auto operator()(R&& r, auto n) const {
    return stride_view(std::forward<R>(r),
      static_cast<range_difference_t<views::all_t<R>>>(n));
  }
  constexpr auto operator()(auto n) const {
    return __stride_closure<decltype(n)>(n);
  }
};
inline constexpr __stride_adaptor stride{};

// ─── cartesian_product(a, b) → function object (not a closure) ──────────────
struct __cartesian_product_adaptor {
  template <viewable_range R1, viewable_range R2>
  constexpr auto operator()(R1&& r1, R2&& r2) const {
    return cartesian_product_view(std::forward<R1>(r1), std::forward<R2>(r2));
  }
};
inline constexpr __cartesian_product_adaptor cartesian_product{};

// ─── join_with(sep) → returns a closure ─────────────────────────────────────
template <class P>
struct __join_with_closure : std::ranges::range_adaptor_closure<__join_with_closure<P>> {
  P pattern_;
  constexpr explicit __join_with_closure(P pattern) : pattern_(pattern) {}
  template <viewable_range R>
  constexpr auto operator()(R&& r) const {
    return join_with_view(std::forward<R>(r), pattern_);
  }
};

struct __join_with_adaptor {
  template <viewable_range R, class P>
  constexpr auto operator()(R&& r, P&& pattern) const {
    return join_with_view(std::forward<R>(r), std::forward<P>(pattern));
  }
  template <class P>
  constexpr auto operator()(P&& pattern) const {
    return __join_with_closure<std::decay_t<P>>(std::forward<P>(pattern));
  }
};
inline constexpr __join_with_adaptor join_with{};

// ─── as_const (no arguments → is itself a closure) ─────────────────────────
struct __as_const_adaptor
  : std::ranges::range_adaptor_closure<__as_const_adaptor> {
  template <viewable_range R>
  constexpr auto operator()(R&& r) const {
    return as_const_view(std::forward<R>(r));
  }
};
inline constexpr __as_const_adaptor as_const{};

} // namespace std::ranges::views

#endif // __cplusplus >= 202100L
#endif // _OMNI_CPP23_RANGES_OVERLAY
