#include #include // for std::declval #include // for std::plus #include #include #include #include #include template > class fold_iterator { public: using iterator_category = std::forward_iterator_tag; using value_type = typename iterator::value_type; using difference_type = void; using pointer = void; using reference = value_type; fold_iterator() = default; value_type operator*() { return op(result, *it); } fold_iterator& operator++() { result = op(result, *it++); return *this; } fold_iterator operator++(int) { auto tmp{*this}; ++*this; return tmp; } bool operator==(fold_iterator const& other) const { return it == other.it; } bool operator!=(fold_iterator const& other) const { return !(*this == other); } private: fold_iterator(iterator it, value_type initial, bin_op op) : it{it}, result{initial}, op{op} {} iterator it{}; value_type result{}; bin_op op{}; template friend class fold; }; template > class fold { using iterator = decltype(std::begin(std::declval())); using value_type = typename iterator::value_type; public: fold(container& c, value_type initial = {}, bin_op op = {}) : first{std::begin(c), initial, op}, last{std::end(c), initial, op} {} fold_iterator begin() { return first; } fold_iterator end() { return last; } private: fold_iterator first, last; }; using namespace std; int main() { { vector vals { 1.0, 1.1, 0.04, 0.0005, 1.001 }; cout << "vector: "; for (auto res : fold(vals)) cout << res << ", "; cout << endl; } { vector vals { 5, 3, 1, 0, 1 }; cout << "vector: "; for (auto res : fold(vals, 10, minus{})) cout << res << ", "; cout << endl; } { list vals { "du", " hast", " mich" }; cout << "list: "; for (auto res : fold(vals)) cout << res << ", "; cout << endl; } { deque> vals { {1, 1}, {5, 2}, {2, 5}, {2, 1}, {0, 1} }; cout << "deque>: "; for (auto res : fold(vals, pair{0, 0}, [](auto a, auto b) { return pair{a.first + b.first, a.second + b.second}; } )) cout << "(" << res.first << ", " << res.second << "), "; cout << endl; } { deque vals {}; cout << "deque: "; for (auto res : fold(vals)) cout << res << ", "; cout << endl; } }