120 lines
2.7 KiB
C++
120 lines
2.7 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// \(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);
|
|
}
|