self_iterating_contianer.hpp 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. #pragma once
  2. namespace stream { namespace detail {
  3. template <typename C, typename It = typename C::const_iterator>
  4. class self_iterating_container {
  5. private:
  6. std::ptrdiff_t offset{0};
  7. C container;
  8. It current;
  9. It end;
  10. public:
  11. self_iterating_container() = default;
  12. self_iterating_container(C const & container)
  13. : container(container), current(container.cbegin()),
  14. end(container.cend()) {}
  15. self_iterating_container(C && container)
  16. : container(std::move(container)), current(container.cbegin()),
  17. end(container.cend()) {}
  18. self_iterating_container(self_iterating_container const & other) {
  19. *this = other;
  20. }
  21. self_iterating_container(self_iterating_container && other) {
  22. *this = std::move(other);
  23. }
  24. self_iterating_container & operator=(self_iterating_container const & other) {
  25. offset = other.offset;
  26. container = other.container;
  27. setup();
  28. return *this;
  29. }
  30. self_iterating_container & operator=(self_iterating_container && other) {
  31. offset = other.offset;
  32. container = std::move(other.container);
  33. setup();
  34. return *this;
  35. }
  36. void operator++() {
  37. ++offset;
  38. ++current;
  39. }
  40. auto& operator*() const { return *current; }
  41. operator bool() const { return current != end; }
  42. private:
  43. void setup() {
  44. current = container.cbegin();
  45. end = container.cend();
  46. std::advance(current, offset);
  47. }
  48. };
  49. }}