iota.h 1.6 KB

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