// // view.h // stream // // Created by Sam Jaffe on 3/29/23. // #pragma once namespace stream::ranges { template class view_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 view_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(view_iterator const & other) const { return impl_ == other.impl_ || (impl_ && other.impl_ && equal_to_(impl_.get(), other.impl_.get())); } }; template class view { private: using make_iter_t = view_iterator(*)(void*); private: std::shared_ptr impl_{nullptr}; make_iter_t begin_{nullptr}; make_iter_t end_{nullptr}; public: template view(std::shared_ptr impl) : impl_(impl), begin_(begin_function()), end_(end_function()) {} 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()); } private: template static make_iter_t begin_function() { if constexpr (traits::is_sentinal_v) { return [](void *p) -> view_iterator { return iterator::sentinel_iterator(static_cast(p)->begin()); }; } else { return [](void * p) -> view_iterator { return static_cast(p)->begin(); }; } } template static make_iter_t end_function() { if constexpr (traits::is_sentinal_v) { return [](void *p) -> view_iterator { return iterator::sentinel_iterator>(); }; } else { return [](void * p) -> view_iterator { return static_cast(p)->end(); }; } } }; template view(std::shared_ptr) -> view>; template view(S &) -> view>; template view(S const &) -> view>; template view(S &&) -> view>; }