#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; // TODO: make 1 constructor that generates a value, move/copy value in all // other constructors generated_iterator() = default; explicit generated_iterator(F &&gen) : generator(std::move(gen)), value(gen()) {} generated_iterator(const generated_iterator &other) : generator(other.generator), value(other.value) {} generated_iterator(generated_iterator &&other) : generator(std::move(other.generator)), value(std::move(other.value)) {} auto operator=(const generated_iterator &other) -> generated_iterator & { generator = other.generator; value = other.value; return *this; } auto operator=(generated_iterator &&other) -> generated_iterator & { generator = std::move(other.generator); value = std::move(other.value); return *this; } 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> { detail::generated_iterator iter_{}; public: constexpr generated_view() = default; constexpr generated_view(F generator) : iter_(detail::generated_iterator(std::move(generator))) {} constexpr auto begin() const { return iter_; } 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