Iterators for circular structures
If it were me, I'd have operator++
notice the terminal condition, and set c
to some sentinal value:
circulator(circ& c) : c(&c), start(&c) {}
circulator& operator++() { c = c->next; if(c==start) c=nullptr; return *this; }
Usage:
circulator begin{a}, end;
while(begin != end) {
begin++;
}
Note that this usage defines the end iterator as holding a nullptr, which means that you can't do this:
circulator end;
--end;
Is there something akin to a looping (circular) iterator?
A generator function could be that. Boost Iterator has the iterator adaptor for that:
- http://www.boost.org/doc/libs/1_52_0/libs/utility/generator_iterator.htm
A sample: http://coliru.stacked-crooked.com/a/267279405be9289d
#include <iostream>
#include <functional>
#include <algorithm>
#include <iterator>
#include <boost/generator_iterator.hpp>
int main()
{
const std::string data = "hello";
auto curr = data.end();
std::function<char()> gen = [curr,data]() mutable -> char
{
if (curr==data.end())
curr = data.begin();
return *curr++;
};
auto it = boost::make_generator_iterator(gen);
std::copy_n(it, 35, std::ostream_iterator<char>(std::cout, ";"));
}
Is there a standard cyclic iterator in C++
There is nothing like this in the standard. Cycles don't play well with C++ iterators because a sequence representing the entire cycle would have first == last
and hence be the empty sequence.
Possibly you could introduce some state into the iterator, a Boolean flag to represent "not done yet." The flag participates in comparison. Set it true
before iterating and to false
upon increment/decrement.
But it might just be better to manually write the algorithms you need. Once you've managed to represent the whole cycle, representing an empty sequence might have become impossible.
EDIT: Now I notice that you specified the number of cycles. That makes a big difference.
template< class I >
class cyclic_iterator
/* : public iterator< bidirectional, yadda yadda > */ {
I it, beg, end;
int cnt;
cyclic_iterator( int c, I f, I l )
: it( f ), beg( f ), end( l ), cnt( c ) {}
public:
cyclic_iterator() : it(), beg(), end(), cnt() {}
cyclic_iterator &operator++() {
++ it;
if ( it == end ) {
++ cnt;
it = beg;
}
} // etc for --, post-operations
friend bool operator==
( cyclic_iterator const &lhs, cyclic_iterator const &rhs )
{ return lhs.it == rhs.it && lhs.cnt == rhs.cnt; } // etc for !=
friend pair< cyclic_iterator, cyclic_iterator > cycle_range
( int c, I f, I l ) {//factory function, better style outside this scope
return make_pair( cyclic_iterator( 0, f, l ),
cyclic_iterator( c, f, l ) );
}
};
How to properly use boost::iterator_adaptor for making cycling iterator?
Have you tried to do something like this:
template<class IteratorBase>
class cycle_iterator : public // (...)
{
// (...)
operator IteratorBase() {
return base_reference();
}
};
Is there something like circular_advance avaliable in std or boost?
I am not aware of any function like that, but this answer shows how to use Boost.Iterator to create an iterator adaptor that cycles over a collection.
C++ Scrolling through items in an stl::map
You can do this with a template. As was stated by a previous poster, this can be cumbersome from the standpoint that it never reaches the end so the user must somehow control this. I'm assuming you have a good reason, perhaps producing some round robin behavior.
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>
using namespace std;
template <class T>
class ScrollIterator
{
public:
ScrollIterator(T &myCtr, typename T::iterator pos)
:ctr(myCtr),
it(pos)
{
}
ScrollIterator operator++()
{
if (++it == ctr.end()) { it = ctr.begin(); }
return *this;
}
bool operator!=(const ScrollIterator &rhs) const
{
return (this->it != rhs.it);
}
bool operator!=(const typename T::const_iterator &rhsIT) const
{
return (this->it != rhsIT);
}
typename T::value_type operator*() const
{
return *it;
}
private:
T &ctr;
typename T::iterator it;
};
int main (int argc, char *argv[])
{
vector<int> v;
v.push_back(2);
v.push_back(3);
v.push_back(5);
v.push_back(7);
int i = 0;
for (ScrollIterator<vector<int> > it(v,v.begin()); it != v.end() && i < 10; ++i, ++it)
{
cout << "Vector = " << i << " Value: " << *it << "\n";
}
set<string> s;
s.insert("c");
s.insert("a");
s.insert("b");
i = 0;
for (ScrollIterator<set<string> > it(s,s.begin()); it != s.end() && i < 10; ++i, ++it)
{
cout << "Set = " << i << " Value: " << *it << "\n";
}
map<string, int> y;
y["z"] = 10;
y["y"] = 20;
y["x"] = 30;
i = 0;
for (ScrollIterator<map<string, int> > it(y,y.begin()); it != y.end() && i < 10; ++i, ++it)
{
cout << "Map = " << i << " Iterator: " << (*it).first << " = " << (*it).second << "\n";
}
return 1;
}
Related Topics
What Are Uses of the C++ Construct "Placement New"
Pair<Int,Int> Pair as Key of Unordered_Map Issue
Convert Char Array to Single Int
C++ Class Wrapper Around Fundamental Types
Why Does the Main Function Work with No Return Value
Does C and C++ Guarantee the Ascii of [A-F] and [A-F] Characters
C++11 Variable Number of Arguments, Same Specific Type
Cannot Create Constexpr Std::Vector
Branchless Code That Maps Zero, Negative, and Positive to 0, 1, 2
C++11 Virtual Destructors and Auto Generation of Move Special Functions
Comparing 3 Modern C++ Ways to Convert Integral Values to Strings
Pointer to Array of Unspecified Size "(*P)[]" Illegal in C++ But Legal in C
Object Oriented Programming in Haskell
What Is the Purpose of Ref-Qualified Member Functions
Lto, Devirtualization, and Virtual Tables
Why Doesn't C++ Make the Structure Tighter
Using Std::Map<K,V> Where V Has No Usable Default Constructor