| 779 | // --------------------------------------------------------------------------- |
| 780 | template <class T, class row_it, class col_it, class iter_type> |
| 781 | class Two_d_iterator |
| 782 | { |
| 783 | public: |
| 784 | typedef Two_d_iterator iterator; |
| 785 | typedef iter_type iterator_category; |
| 786 | typedef T value_type; |
| 787 | typedef std::ptrdiff_t difference_type; |
| 788 | typedef T* pointer; |
| 789 | typedef T& reference; |
| 790 | |
| 791 | explicit Two_d_iterator(row_it curr) : row_current(curr), col_current(0) |
| 792 | { |
| 793 | if (row_current && !row_current->is_marked()) |
| 794 | { |
| 795 | col_current = row_current->ne_begin(); |
| 796 | advance_past_end(); // in case cur->begin() == cur->end() |
| 797 | } |
| 798 | } |
| 799 | |
| 800 | explicit Two_d_iterator(row_it curr, col_it col) : row_current(curr), col_current(col) |
| 801 | { |
| 802 | assert(col); |
| 803 | } |
| 804 | |
| 805 | // The default constructor |
| 806 | Two_d_iterator() : row_current(0), col_current(0) { } |
| 807 | |
| 808 | // Need this explicitly so we can convert normal iterators <=> const iterators |
| 809 | // not explicit on purpose |
| 810 | // --------------------------------------------------------------------------- |
| 811 | template <class T2, class row_it2, class col_it2, class iter_type2> |
| 812 | Two_d_iterator(const Two_d_iterator<T2, row_it2, col_it2, iter_type2>& it) : |
| 813 | row_current (*(row_it *)&it.row_current), |
| 814 | col_current (*(col_it *)&it.col_current) |
| 815 | { } |
| 816 | |
| 817 | // The default destructor is fine; we don't define one |
| 818 | // The default operator= is fine; we don't define one |
| 819 | |
| 820 | value_type& operator*() const { return *(col_current); } |
| 821 | value_type* operator->() const { return &(operator*()); } |
| 822 | |
| 823 | // Arithmetic: we just do arithmetic on pos. We don't even need to |
| 824 | // do bounds checking, since STL doesn't consider that its job. :-) |
| 825 | // NOTE: this is not amortized constant time! What do we do about it? |
| 826 | // ------------------------------------------------------------------ |
| 827 | void advance_past_end() |
| 828 | { |
| 829 | // used when col_current points to end() |
| 830 | while (col_current == row_current->ne_end()) |
| 831 | { |
| 832 | // end of current row |
| 833 | // ------------------ |
| 834 | ++row_current; // go to beginning of next |
| 835 | if (!row_current->is_marked()) // col is irrelevant at end |
| 836 | col_current = row_current->ne_begin(); |
| 837 | else |
| 838 | break; // don't go past row_end |