#pragma once #include <optional> #include <ranges> #include <xutility> namespace util { namespace rg = std::ranges; namespace detail { template <rg::input_range R> constexpr auto get_first(R &&r) -> std::optional<rg::range_value_t<R>> { if (rg::begin(r) == rg::end(r)) { return std::nullopt; } else { return *rg::begin(r); } } struct first_range_adaptor { template <rg::input_range R> constexpr auto operator()(R &&r) const { return get_first(std::forward<R>(r)); } }; template <rg::viewable_range R> constexpr auto operator|(R &&r, const first_range_adaptor &adaptor) { return adaptor(std::forward<R>(r)); } } // namespace detail namespace views { inline detail::first_range_adaptor first; } template <rg::range R> constexpr auto get_first(R &&r) -> std::optional<rg::range_value_t<R>>{ return r | views::first; } } // namespace util