view.h 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. //
  2. // view.h
  3. // stream
  4. //
  5. // Created by Sam Jaffe on 3/29/23.
  6. //
  7. #pragma once
  8. namespace stream::ranges {
  9. template <typename T> class view {
  10. public:
  11. class iterator : public facade<iterator> {
  12. private:
  13. T (*dereference_)(void *){nullptr};
  14. bool (*equal_to_)(void *, void *){nullptr};
  15. void (*increment_)(void *){nullptr};
  16. std::shared_ptr<void> impl_{nullptr};
  17. public:
  18. template <typename It>
  19. iterator(It impl)
  20. : dereference_([](void * p) -> T { return **((It *)p); }),
  21. equal_to_(
  22. [](void * l, void * r) { return *((It *)l) == *((It *)r); }),
  23. increment_([](void * p) { ++(*(It *)(p)); }),
  24. impl_(std::make_shared<It>(impl)) {}
  25. T dereference() const { return dereference_(impl_.get()); }
  26. void increment() { increment_(impl_.get()); }
  27. bool equal_to(iterator const & other) const {
  28. return impl_ == other.impl_ ||
  29. (impl_ && other.impl_ &&
  30. equal_to_(impl_.get(), other.impl_.get()));
  31. }
  32. };
  33. private:
  34. std::shared_ptr<void> impl_{nullptr};
  35. iterator (*begin_)(void *){nullptr};
  36. iterator (*end_)(void *){nullptr};
  37. public:
  38. template <typename S>
  39. view(std::shared_ptr<S> impl)
  40. : impl_(impl), begin_([](void * p) -> iterator {
  41. return static_cast<S *>(p)->begin();
  42. }),
  43. end_([](void * p) -> iterator { return static_cast<S *>(p)->end(); }) {}
  44. template <typename S>
  45. view(S & impl) : view(std::shared_ptr<S>(&impl, [](void *) {})) {}
  46. template <typename S>
  47. view(S const & impl) : view(std::shared_ptr<S const>(&impl, [](void *) {})) {}
  48. template <typename S>
  49. view(S && impl) : view(std::make_shared<S>(std::forward<S>(impl))) {}
  50. auto begin() const { return begin_(impl_.get()); }
  51. auto end() const { return end_(impl_.get()); }
  52. bool empty() const { return begin() == end(); }
  53. };
  54. }