blob: 1d576cf6f08f6c4791a10142552da48282c47fb7 [file] [log] [blame]
//////////////////////////////////////////////////////////////////////////////
//
// \(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 <typename Container>
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 <typename Container>
input_iterator<Container> make_input_iterator(Container& c, typename Container::iterator it)
{
return input_iterator<Container>(c, it);
}