// // view.h // stream // // Created by Sam Jaffe on 3/29/23. // #pragma once namespace stream::ranges { template class view { public: class iterator : public facade { private: T (*dereference_)(void *){nullptr}; bool (*equal_to_)(void *, void *){nullptr}; void (*increment_)(void *){nullptr}; std::shared_ptr impl_{nullptr}; public: template iterator(It impl) : dereference_([](void * p) -> T { return **((It *)p); }), equal_to_( [](void * l, void * r) { return *((It *)l) == *((It *)r); }), increment_([](void * p) { ++(*(It *)(p)); }), impl_(std::make_shared(impl)) {} T dereference() const { return dereference_(impl_.get()); } void increment() { increment_(impl_.get()); } bool equal_to(iterator const & other) const { return impl_ == other.impl_ || (impl_ && other.impl_ && equal_to_(impl_.get(), other.impl_.get())); } }; private: std::shared_ptr impl_{nullptr}; iterator (*begin_)(void *){nullptr}; iterator (*end_)(void *){nullptr}; public: template view(std::shared_ptr impl) : impl_(impl), begin_([](void * p) -> iterator { return static_cast(p)->begin(); }), end_([](void * p) -> iterator { return static_cast(p)->end(); }) {} template view(S & impl) : view(std::shared_ptr(&impl, [](void *) {})) {} template view(S const & impl) : view(std::shared_ptr(&impl, [](void *) {})) {} template view(S && impl) : view(std::make_shared(std::forward(impl))) {} auto begin() const { return begin_(impl_.get()); } auto end() const { return end_(impl_.get()); } bool empty() const { return begin() == end(); } }; }