| 44 | : base_map_(map), transform_(transform), transform_back_(transform_back){} |
| 45 | |
| 46 | class iterator { |
| 47 | public: |
| 48 | using base_iterator = typename BaseMap::iterator; |
| 49 | using iterator_category = std::forward_iterator_tag; |
| 50 | using difference_type = typename std::iterator_traits<base_iterator>::difference_type; |
| 51 | using key_type = typename BaseMap::key_type; |
| 52 | using transformed_mapped_type = std::invoke_result_t<Transform, typename BaseMap::mapped_type>; |
| 53 | using value_type = std::pair<key_type, transformed_mapped_type>; |
| 54 | |
| 55 | private: |
| 56 | base_iterator base_it_; |
| 57 | Transform* transform_ptr_; |
| 58 | |
| 59 | mutable value_type cached_value_; |
| 60 | |
| 61 | public: |
| 62 | iterator() : base_it_(), transform_ptr_(nullptr) {} |
| 63 | iterator(base_iterator base_it, Transform* transform_ptr) |
| 64 | : base_it_(base_it), transform_ptr_(transform_ptr) {} |
| 65 | |
| 66 | // On dereference, return a pair where the key is unchanged and the mapped value |
| 67 | // is the result of applying the transform to the underlying mapped value. |
| 68 | // @todo should these also all be const references so that key/value can be non-copyable (i.e unique_ptr) |
| 69 | value_type operator*() const { |
| 70 | auto base_val = *base_it_; |
| 71 | return { base_val.first, (*transform_ptr_)(base_val.second) }; |
| 72 | } |
| 73 | |
| 74 | // operator-> uses a mutable cache to return a pointer to the current value. |
| 75 | value_type* operator->() const { |
| 76 | cached_value_ = **this; |
| 77 | return &cached_value_; |
| 78 | } |
| 79 | |
| 80 | iterator& operator++() { |
| 81 | ++base_it_; |
| 82 | return *this; |
| 83 | } |
| 84 | |
| 85 | iterator operator++(int) { |
| 86 | iterator tmp(*this); |
| 87 | ++(*this); |
| 88 | return tmp; |
| 89 | } |
| 90 | |
| 91 | bool operator==(const iterator& other) const { |
| 92 | return base_it_ == other.base_it_; |
| 93 | } |
| 94 | |
| 95 | bool operator!=(const iterator& other) const { |
| 96 | return !(*this == other); |
| 97 | } |
| 98 | }; |
| 99 | |
| 100 | iterator begin() { |
| 101 | return iterator(base_map_->begin(), &transform_); |