#pragma once #include namespace util { namespace rg = std::ranges; template requires rg::view class drop_last_view : public rg::view_interface> { private: R base_{}; std::iter_difference_t> count_{}; rg::iterator_t iter_{std::begin(base_)}; public: drop_last_view() = default; constexpr drop_last_view(R base, std::iter_difference_t> count) : base_(base), count_(count), iter_(std::begin(base_)) {} constexpr R base() const & { return base_; } constexpr R base() && { return std::move(base_); } constexpr auto begin() const { return iter_; } constexpr auto end() const { return std::end(base_) - count_; } constexpr auto size() const requires rg::sized_range { const auto s = rg::size(base_); const auto c = static_cast(count_); return s < c ? 0 : s - c; } }; namespace detail { struct drop_last_range_adaptor_closure { std::size_t count_; constexpr drop_last_range_adaptor_closure(std::size_t count) : count_(count) {} template constexpr auto operator()(R &&r) const { return drop_last_view(std::forward(r), count_); } }; struct drop_last_range_adaptor { template constexpr auto operator()(R &&r, std::iter_difference_t> count) { return drop_last_view(std::forward(r), count); } constexpr auto operator()(std::size_t count) { return drop_last_range_adaptor_closure(count); } }; template constexpr auto operator|(R &&r, drop_last_range_adaptor_closure const &a) { return a(std::forward(r)); } } // namespace detail namespace views { inline detail::drop_last_range_adaptor drop_last; } // namespace views } // namespace util