iota_view.h 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. //
  2. // iota_view.h
  3. // stream
  4. //
  5. // Created by Sam Jaffe on 3/29/23.
  6. //
  7. #pragma once
  8. #include <iterator/facade.h>
  9. namespace stream::ranges {
  10. template <typename T, typename Bound>
  11. class iota_iterator : public facade<iota_iterator<T, Bound>> {
  12. public:
  13. using sentinal_type = Bound;
  14. iota_iterator() = default;
  15. iota_iterator(T value, Bound bound) : value_(value), bound_(bound) {}
  16. T const & dereference() const { return value_; }
  17. void increment() { ++value_; }
  18. bool at_end() const { return value_ == bound_; }
  19. // Some weird bug in dependent template instantiation???
  20. bool equal_to(iota_iterator const & other) const {
  21. return value_ == other.value_;
  22. }
  23. std::ptrdiff_t distance_to(iota_iterator const & other) const {
  24. return other.value_ - value_;
  25. }
  26. private:
  27. T value_;
  28. Bound bound_;
  29. };
  30. template <typename T, typename Bound> struct iota_view {
  31. public:
  32. constexpr static inline bool has_size_v = std::is_constructible_v<T, Bound>;
  33. private:
  34. T value_;
  35. Bound bound_;
  36. public:
  37. iota_view(T value, Bound bound) : value_(value), bound_(bound) {}
  38. auto begin() const { return iota_iterator(value_, bound_); }
  39. auto end() const {
  40. if constexpr (has_size_v) {
  41. return iota_iterator(bound_, bound_);
  42. } else {
  43. return bound_;
  44. }
  45. }
  46. bool empty() const { return begin().at_end(); }
  47. auto size() const -> std::enable_if_t<has_size_v, size_t> {
  48. return begin().distance_to(end());
  49. }
  50. };
  51. }
  52. namespace stream::ranges::views {
  53. template <typename T, typename Bound> auto iota(T value, Bound bound) {
  54. return iota_view(value, bound);
  55. }
  56. }
  57. MAKE_ITERATOR_FACADE_TYPEDEFS_T(stream::ranges::iota_iterator);