| re: 'Looping' an std::list
In article <1148755600.962259.283320@j55g2000cwa.googlegroups .com>,
"esuvs" <david@david-williams.info> wrote:
[color=blue]
> Hi, I would like to change the behavior of the std::list so that if I
> set an iterator to the last element and increment it I would like it to
> point to the first element, and vice vesa. That is, i would like to use
> it as a circular buffer.
>
> Is this possble? Given that the linked list is probably just a set of
> nodes and 'next' pointers it doesn't seem unreasonable (just set the
> last pointer to point at the start) but I suspect the std::list is to
> safe/robust to allow me to abuse it in this way...
>
> Be great if someone could prove me wrong :-D Otherwise is there an
> STL/Boost container giving this behaviour? I think i could do it with
> boost::graph but seems a bit of a heavyweight solution.[/color]
I posted the below back in March... (Pieter Pareit seems to have posted
something very much like it back in Jan of 2002.)
You can use the circular_iterator on any of the standard containers. The
code below does need some fleshing out (for eg: post-increment and
decrement, operator->() and const dereference operators) but the below
is enough for most uses.
* *template < typename Container >
class circular_iterator_t : public std::iterator<
* * * * * * * *typename Container::iterator::iterator_category,
* * * * * * * *typename Container::iterator::value_type >
{
* *Container& rep;
* *typename Container::iterator loc;
public:
* *explicit circular_iterator_t( Container& container ):
* * * * * * * *rep( container ), loc( container.begin() ) { }
* *circular_iterator_t( Container& container,
* * * * * * * *typename Container::iterator it ):
* * * * * * * *rep( container ), loc( it ) { }
* *typename Container::value_type& operator*() {
* * * return *loc;
* *}
* *circular_iterator_t& operator--() {
* * * if ( loc == rep.begin() )
* * * * *loc = --rep.end();
* * * else
* * * * *--loc;
* * * return *this;
* *}
* *circular_iterator_t& operator++() {
* * * ++loc;
* * * if ( loc == rep.end() )
* * * * *loc = rep.begin();
* * * return *this;
* *}
* *friend bool operator==( const circular_iterator_t& lhs,
* * * * * * * *const circular_iterator_t& rhs ) {
* * * return lhs.rep == rhs.rep && lhs.loc == rhs.loc;
* *}
};
* *template < typename Container >
bool operator!=( const circular_iterator_t<Container>& lhs,
* * * * * * * *const circular_iterator_t<Container>& rhs ) {
* *return !( lhs == rhs );
}
* *template < typename Container >
circular_iterator_t<Container> circular_iterator( Container& container )
{
* *return circular_iterator_t<Container>( container );
}
* *template < typename Container >
circular_iterator_t<Container> circular_iterator( Container& container,
typename Container::iterator it ) {
* *return circular_iterator_t<Container>( container, it );
} |