////////////////////////////////////////////////////////////////////////////// // // \(C\) Copyright Benedek Thaler 2015-2016 // \(C\) Copyright Ion Gaztanaga 2019-2020. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://erenon.hu/double_ended for documentation. // ////////////////////////////////////////////////////////////////////////////// /** * Emulates input iterator, validates algorithm * does a single pass only, removes visited elements. * * Container::erase(front_iterator) must not invalidate other iterators. * * The hack around `_erase_on_destroy` is required to make `*it++` work. */ template class input_iterator { typedef typename Container::iterator iterator; public: typedef std::input_iterator_tag iterator_category; typedef typename Container::value_type value_type; typedef typename Container::pointer pointer; typedef typename Container::reference reference; typedef typename Container::difference_type difference_type; struct erase_on_destroy {}; public: input_iterator() : _container() , _it() , _erase_on_destroy() {} input_iterator(Container& c, iterator it) :_container(&c) , _it(it) , _erase_on_destroy() {} input_iterator(const input_iterator& rhs) :_container(rhs._container), _it(rhs._it), _erase_on_destroy(rhs._erase_on_destroy) { rhs._erase_on_destroy = false; } input_iterator & operator=(const input_iterator& rhs) { _container = rhs._container; _it = rhs._it; _erase_on_destroy = rhs._erase_on_destroy; rhs._erase_on_destroy = false; return *this; } input_iterator(const input_iterator& rhs, erase_on_destroy) :_container(rhs._container), _it(rhs._it), _erase_on_destroy(true) {} ~input_iterator() { if (_erase_on_destroy) { _container->erase(_it); // must not invalidate other iterators } } const value_type& operator*() { return *_it; } input_iterator operator++() { _container->erase(_it); ++_it; return *this; } input_iterator operator++(int) { input_iterator old(*this, erase_on_destroy()); ++_it; return old; } friend bool operator==(const input_iterator a, const input_iterator b) { return a._it == b._it; } friend bool operator!=(const input_iterator a, const input_iterator b) { return !(a == b); } private: Container* _container; iterator _it; mutable bool _erase_on_destroy; }; template input_iterator make_input_iterator(Container& c, typename Container::iterator it) { return input_iterator(c, it); }