#pragma once #include #include #include #include namespace util { namespace rg = std::ranges; namespace detail { template struct generated_iterator { using value_type = decltype(std::declval()()); using reference = value_type &; using difference_type = std::ptrdiff_t; value_type value{}; F generator{}; generated_iterator() = default; generated_iterator(F gen) : generator(gen), value(gen()) {} generated_iterator(F &&gen) : generator(std::move(gen)), value(gen()) {} auto generate_new_value() -> void { value = generator(); } constexpr auto operator==(const generated_iterator &other) const { return false; } auto operator++(int) -> generated_iterator { const auto result = *this; ++(*this); return result; } auto operator++() -> generated_iterator & { generate_new_value(); return (*this); } auto operator*() { return value; } auto operator*() const { return value; } }; } // namespace detail template class generated_view : rg::view_interface> { F generator = {}; public: constexpr generated_view() = default; constexpr generated_view(F generator) : generator(std::move(generator)) {} constexpr auto begin() const { return detail::generated_iterator(generator); } constexpr auto end() const { return std::unreachable_sentinel; } }; namespace detail { struct generated_range_adaptor_closure { template constexpr auto operator()(F &&fn) const { return generated_view(std::forward(fn)); } }; struct generated_range_adaptor { template constexpr auto operator()(F &&r) { return generated_view(std::forward(r)); } constexpr auto operator()() { return generated_range_adaptor_closure(); } }; } // namespace detail namespace views { inline detail::generated_range_adaptor_closure from; } } // namespace util