#pragma once #include #include #include "query/typed_value.hpp" #include "utils/memory.hpp" namespace query { /** * `AnyStream` can wrap *any* type implementing the `Stream` concept into a * single type. * * The type erasure technique is used. The original type which an `AnyStream` * was constructed from is "erased", as `AnyStream` is not a class template and * doesn't use the type in any way. Client code can then program just for * `AnyStream`, rather than using static polymorphism to handle any type * implementing the `Stream` concept. */ class AnyStream final { public: template AnyStream(TStream *stream, utils::MemoryResource *memory_resource) : content_{utils::Allocator>{memory_resource} .template new_object>(stream), [memory_resource](Wrapper *ptr) { utils::Allocator>{memory_resource} .template delete_object>( static_cast *>(ptr)); }} {} void Result(const std::vector &values) { content_->Result(values); } private: struct Wrapper { virtual void Result(const std::vector &values) = 0; }; template struct GenericWrapper final : public Wrapper { explicit GenericWrapper(TStream *stream) : stream_{stream} {} void Result(const std::vector &values) override { stream_->Result(values); } TStream *stream_; }; std::unique_ptr> content_; }; } // namespace query