#pragma once #include "utils/iterator/composable.hpp" #include "utils/iterator/iterator_base.hpp" namespace iter { // Class which maps values returned by I iterator into value of type T with OP // function. // T - type of return value // I - iterator type // OP - type of mapper function template <class T, class I, class OP> class Map : public IteratorBase<T>, public Composable<T, Map<T, I, OP>> { public: Map() = delete; // Map operation is designed to be used in chained calls which operate on a // iterator. Map will in that usecase receive other iterator by value and // std::move is a optimization for it. Map(I &&iter, OP &&op) : iter(std::move(iter)), op(std::move(op)) {} Map(Map &&m) : iter(std::move(m.iter)), op(std::move(m.op)) {} ~Map() final {} Option<T> next() final { auto item = iter.next(); if (item.is_present()) { return Option<T>(op(item.take())); } else { return Option<T>(); } } Count count() final { return iter.count(); } private: I iter; OP op; }; template <class I, class OP> auto make_map(I &&iter, OP &&op) { // Compiler cant deduce type T. decltype is here to help with it. return Map<decltype(op(iter.next().take())), I, OP>(std::move(iter), std::move(op)); } }