68 lines
1.8 KiB
C++
68 lines
1.8 KiB
C++
#pragma once
|
|
#include <ranges>
|
|
|
|
namespace util {
|
|
namespace rg = std::ranges;
|
|
|
|
template <rg::sized_range R>
|
|
requires rg::view<R>
|
|
class drop_last_view : public rg::view_interface<drop_last_view<R>> {
|
|
private:
|
|
R base_{};
|
|
std::iter_difference_t<rg::iterator_t<R>> count_{};
|
|
rg::iterator_t<R> iter_{std::begin(base_)};
|
|
|
|
public:
|
|
drop_last_view() = default;
|
|
|
|
constexpr drop_last_view(R base,
|
|
std::iter_difference_t<rg::iterator_t<R>> 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 R> {
|
|
const auto s = rg::size(base_);
|
|
const auto c = static_cast<decltype(s)>(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 <rg::viewable_range R> constexpr auto operator()(R &&r) const {
|
|
return drop_last_view(std::forward<R>(r), count_);
|
|
}
|
|
};
|
|
|
|
struct drop_last_range_adaptor {
|
|
template <rg::viewable_range R>
|
|
constexpr auto operator()(R &&r,
|
|
std::iter_difference_t<rg::iterator_t<R>> count) {
|
|
return drop_last_view(std::forward<R>(r), count);
|
|
}
|
|
|
|
constexpr auto operator()(std::size_t count) {
|
|
return drop_last_range_adaptor_closure(count);
|
|
}
|
|
};
|
|
|
|
template <rg::viewable_range R>
|
|
constexpr auto operator|(R &&r, drop_last_range_adaptor_closure const &a) {
|
|
return a(std::forward<R>(r));
|
|
}
|
|
} // namespace detail
|
|
|
|
namespace views {
|
|
inline detail::drop_last_range_adaptor drop_last;
|
|
} // namespace views
|
|
|
|
} // namespace util
|