I have the following code:
Where I stupidly iterate over a container (self-written).
If I compile this function with the cout it works and the program terminates correctly after the iteration! Note: The cout does not interfere with the self-made container!
If I then comment it out, the test starts to take infinitely long and does not terminate!
My eyeballs where almost dropping inside my head! What the hack is going on here???
My first guess was, that the compiler does something wrong? (but why?) or that maybe branch prediction plays me wrong and somehow increments the iterator twice? (which will result in no end() iterator).
I can really not explain what is going on?
int loops = 100;
int n = 0;
RangeTypes<Type>::ContainerType range(a);
INIT_TIMER
START_TIMER
for(int i=1; i<loops; i++) {
for(auto it=range.begin(); it != range.end(); ++it) {
n += *it;
//std::cout << i << std::endl;
}
}
STOP_TIMER("Range: ")
Actually the RangeType Container looks like this, and is pretty simple, it takes a range, and iterates from start to end!
template<typename Type>
struct RangeTypes {
using RangeType = std::pair<Type,Type> ;
class Iterator {
public:
Iterator(): m_rangePtr(nullptr), m_currVal(0) {};
~Iterator() {};
Iterator(RangeType & range, bool atEnd=false): m_rangePtr(&range) {
if(atEnd) {
m_currVal = m_rangePtr->second;
} else {
m_currVal = m_rangePtr->first;
}
};
/** pre-increment ++it
* Allow to iterate over the end of the sequence
*/
Iterator & operator++() {
if(m_rangePtr) {
++m_currVal;
}
return *this;
}
/** post-increment it++ */
Iterator operator++(int) {
Iterator it(*this);
operator++();
return it;
}
bool operator==(const Iterator &rhs) {
if(m_rangePtr) {
if(m_rangePtr == rhs.m_rangePtr ) { // if sequences are the same
return m_currVal == rhs.m_currVal;
}
}
return false;
}
// Return false if the same!
bool operator!=(const Iterator &rhs) {
return !(*this==rhs);
}
// get current value;
Type operator*() {
return m_currVal;
}
private:
RangeType * m_rangePtr;
Type m_currVal;
};
class ContainerType : public RangeType {
public:
typedef Iterator iterator;
ContainerType(RangeType & range ): RangeType(range) {
// if range wrong, set to no range!
if(this->first > this->second) {
this->first = 0;
this->second = 0;
}
}
iterator begin() {
return iterator(*this);
};
iterator end() {
return iterator(*this,true);
};
};
};
HERE IS THE MWE: Compiled Example
Thanks for any help!!
Related
I want to implement a custom iterator class that has some differences with typical iterators. The container in this example is a vector and the idea is to walk throw it but using a specific syntax, like this:
int main()
{
VectorElement E;
for (size_t i = 0; i < 5; i++)
{
Element e;
e.id = i;
E.push_back(e);
}
for (ElementIterator e(E); e.end(); ++e)
cout << "Element " << e.id << endl;
}
I tried with the following definitions, but it gives me a Segmentation Fault at the static_cast line after two iterations. Does someone know how to improve this? Thanks
class Element
{
public:
Element() {};
size_t id;
};
typedef vector<Element> VectorElement;
class ElementIterator: public Element
{
typedef vector<Element>::iterator iter;
public:
ElementIterator(const Element& e) : Element(e) { }
ElementIterator(VectorElement& ve_)
{
ve = &ve_;
it = ve->begin();
}
ElementIterator operator++()
{
++it;
*this = static_cast<ElementIterator>(*it);
return *this;
}
bool end()
{
if (it != ve->end() )
return true;
return false;
}
vector<Element>* ve;
iter it;
};
Here is alternate implementation that does not rely on global variables or deriving from 'Element':
class Element
{
public:
Element() {};
size_t id;
};
class ElementIterator
{
std::vector<Element>& ve;
std::vector<Element>::iterator it;
public:
ElementIterator(std::vector<Element>& ve_) : ve(ve_)
{
it = ve.begin();
}
ElementIterator(const ElementIterator &rhs) : ve(rhs.ve)
{
it = rhs.it;
}
ElementIterator operator++()
{
++it;
return *this;
}
const Element *operator ->() const
{
assert(!this->end());
return &(*it);
}
bool end() const
{
if (it == ve.end())
return true;
return false;
}
};
Main:
int main()
{
std::vector<Element> E;
for (size_t i = 0; i < 5; i++)
{
Element e;
e.id = i;
E.push_back(e);
}
for (ElementIterator e(E); !e.end(); ++e)
std::cout << "Element " << e->id << std::endl;
}
NOTE: I changed the behaviour of 'ElementIterator::end' so that it returns 'true' when it is at the end which seemed more logical.
Try it here:
http://coliru.stacked-crooked.com/a/8bf8b1025d87a882
I suspect that the segfault occurs because the 'ElementIterator::operator++()' increments the internal 'it' attribute and then deferences it without verifying that its valid first. It could be implemented as follows:
ElementIterator::operator ++()
{
++it;
if (!this->end())
*this = static_cast<ElementIterator>(*it);
return *this;
}
I finally use this workaround, that it is not elegant but works. The main problem was that the iterator "it" was overwritten so I put it in the global scope.
class Element
{
public:
Element() {};
size_t id;
};
typedef vector<Element> VectorElement;
typedef vector<Element>::iterator iter;
iter it;
class ElementIterator: public Element
{
public:
ElementIterator(const Element& e) : Element(e) { }
ElementIterator(VectorElement& ve_)
{
ve = &ve_;
it = ve->begin();
}
ElementIterator operator++()
{
++it;
*this = static_cast<ElementIterator>(*it);
return *this;
}
bool end()
{
if (it != ve->end() )
return true;
return false;
}
vector<Element>* ve;
};
I'm trying to implement a container in C++ that uses a flat array to store the data but iterates over that data in pairs. Now I could easily change the implementation such that the container holds a vector of std::pair however I want to iterate through pairs starting at element 0 or at element 1.
To illustrate what I want to achieve, if my underlying array looks like:
1,2,3,4,5,6,7,8
I want to define two iterators, one which returns the pairs:
(1,2), (3,4), (5,6), (7,8)
and the second iterator to return the pairs:
(2,3), (4,5), (6,7)
is this possible to do while still allowing the elements of the iterator to be references of the underlying array?
It is possible to write your own iterator, which iterates over the elements. The following question shows some explanations on how that is done:
Custom Iterator in C++.
You can then return the desired values as std::pair and iterate to the next element-pair (by incrementing the counter by 2).
Boost library has got Iterator Adaptor that allows you to wrap other iterator types and change or adapt their functionality. Here's how you could use it for your purpose:
#include <boost/iterator/iterator_adaptor.hpp>
#include <vector>
struct iterator :
public boost::iterator_adaptor<
iterator, // the name of our class, see docs for details
std::vector<int>::iterator, // underlying base iterator
std::pair<int&, int&>, // our value type
boost::forward_traversal_tag // the category you wish to give it
>
{
// need this to convert from vector::iterator to ours
explicit iterator(std::vector<int>::iterator i)
: iterator::iterator_adaptor_(i) {}
value_type operator*()
{
return value_type(
*base_reference(),
*(base_reference()+1)
);
}
};
Example of usage:
std::vector<int> v {1,2,3,4};
iterator it(v.begin());
++it;
(*it).first = 0; // TODO: operator->
(*it).second = 0;
for (int i : v) std::cout << i << ' '; // prints 1 0 0 4
You'll also need to override comparison to properly handle end condition, etc. Hope that helps.
Just thought I'd put in what I actually used in my code. I didn't want to use boost as suggested by #jrok but the type std::pair<int&, int&> in their answer gave me a hint of what was required.
Below is the class that I constructed which uses two iterators. A RepeatIterator that returns pairs starting on even indexes in the underlying data, and a SpacerIterator that returns pairs starting on odd indexes.
class RepeatArray {
typedef std::vector<int> storage_t;
public:
class RepeatIterator {
public:
typedef RepeatIterator self_t;
typedef int value_t;
typedef int& reference_t;
typedef int* pointer_t;
typedef std::pair<reference_t, reference_t> return_t;
RepeatIterator(storage_t::iterator input) : current_pos(input){}
return_t operator *() {
return return_t(*(current_pos), *(current_pos + 1 ));
}
self_t operator++() { self_t i = *this; current_pos += 2; return i; }
self_t operator++(int junk) { current_pos+=2; return *this; }
bool operator==(const self_t& rhs) { return current_pos == rhs.current_pos; }
bool operator!=(const self_t& rhs) { return current_pos != rhs.current_pos; }
bool operator<(const self_t& rhs) { return current_pos < rhs.current_pos; }
bool operator<=(const self_t& rhs) { return current_pos <= rhs.current_pos; }
bool operator>(const self_t& rhs) { return current_pos > rhs.current_pos; }
bool operator>=(const self_t& rhs) { return current_pos >= rhs.current_pos; }
private:
storage_t::iterator current_pos;
};
class SpacerIterator {
public:
typedef SpacerIterator self_t;
typedef int value_t;
typedef int& reference_t;
typedef int* pointer_t;
typedef std::pair<reference_t, reference_t> return_t;
SpacerIterator(storage_t::iterator input) : current_pos(input){}
return_t operator *() {
return return_t(*(current_pos), *(current_pos + 1 ));
}
self_t operator++() { self_t i = *this; current_pos += 2; return i; }
self_t operator++(int junk) { current_pos+=2; return *this; }
bool operator==(const self_t& rhs) { return current_pos == rhs.current_pos; }
bool operator!=(const self_t& rhs) { return current_pos != rhs.current_pos; }
bool operator<(const self_t& rhs) { return current_pos < rhs.current_pos; }
bool operator<=(const self_t& rhs) { return current_pos <= rhs.current_pos; }
bool operator>(const self_t& rhs) { return current_pos > rhs.current_pos; }
bool operator>=(const self_t& rhs) { return current_pos >= rhs.current_pos; }
private:
storage_t::iterator current_pos;
};
void add(int start, int end) {
positions.push_back(start);
positions.push_back(end);
}
void dump() {
for (auto i : positions) {
std::cout <<i<<",";
}
std::cout <<std::endl;
}
RepeatIterator repeatBegin(){return RepeatIterator(positions.begin());}
RepeatIterator repeatEnd(){return RepeatIterator(positions.end());}
SpacerIterator spacerBegin(){return SpacerIterator(positions.begin() + 1);}
SpacerIterator spacerEnd(){return SpacerIterator(positions.end() - 1);}
protected:
storage_t positions;
};
And then the tesing program compiled using clang++ -std=c++0x -o testRepeatArray RepeatArray.cpp
int main() {
RepeatArray r = RepeatArray();
r.add(1,3);
r.add(7,12);
std::cout<<"original:"<<std::endl;
r.dump();
std::cout << "Testing Repeat iterator:"<<std::endl;
for (RepeatArray::RepeatIterator it2 = r.repeatBegin(); it2 != r.repeatEnd(); ++it2) {
std::cout << (*it2).first <<","<< (*it2).second << std::endl;
}
std::cout << "Testing Spacer iterator:"<<std::endl;
for (RepeatArray::SpacerIterator it3 = r.spacerBegin(); it3 != r.spacerEnd(); ++it3) {
std::cout << (*it3).first <<","<< (*it3).second << std::endl;
}
std::cout<<"Testing modification:"<<std::endl;
RepeatArray::RepeatIterator it = r.repeatBegin();
(*it).first = 0;
(*it).second = 123;
r.dump();
return 0;
}
I am writing codes for a template class with linked list and vectors of pointers to some nodes in the linked list. The code is ugly because I just wrote what I thought might work, and corrected it focusing on fixing the error messages.
The list (accordingly, the vector, too) is kept sorted because it finds the right position with position method every time it insert an item.
Initially, I had a lot of errors, and I was able to fix them after a lot of trying.
Now it compiles, but when I tested it with a main method if this template class works fine, it throws an error message:
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check
Aborted (core dumped)
I know what std::out_of_range is, but I really do not see why this error occurs.
There is not even many parts in my code that accesses elements of the vector.
The following is the code for the testing main method, and the next is the definition for my template class(and the nested iterator class).
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <vector>
#include "ValliHN.h"
using namespace std;
int main() {
Valli<string> valli;
valli.insert("K");
valli.insert("H");
valli.insert("N");
valli.insert("H");
valli.insert("J");
for (Valli<string>::iterator i = valli.begin(); i != valli.end(); i++)
cout << *i << endl;
return 0;
}
The template class
#include"DList.h"
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdlib>
using std::cout;
using std::endl;
using std::cerr;
using std::vector;
template<typename I>
class Valli {
vector< DNode<I>* > va;
DList<I> lli;
size_t ratio;
friend class iterator;
friend class DList<I>;
public:
class iterator {
typename DList<I>::iterator list_iter;
iterator(DNode<I>* node)
: list_iter(typename DList<I>::iterator(node)) { }
friend class Valli<I>;
friend class DList<I>;
public:
I& operator*() const {
return *list_iter;
}
iterator& operator++() {
++list_iter;
return *this;
}
iterator operator++(int) {
iterator* ret = this;
++list_iter;
return *ret;
}
iterator& operator--() {
--list_iter;
return *this;
}
iterator operator--(int) {
typename DList<I>::iterator ret = list_iter;
--list_iter;
return ret;
}
bool operator==(const iterator& rhs) const {
return list_iter == rhs.list_iter;
}
bool operator!=(const iterator& rhs) const {
return list_iter != rhs.list_iter;
}
DNode<I>* returnCurr() const {
return list_iter.returnCurr();
}
};
explicit Valli<I>(size_t ratio=4)
: ratio(ratio),
lli(DList<I>()),
va(vector< DNode<I>* >()) { }
// Valli<I>()
// : Valli<I>(4) { }
~Valli<I>() {
// delete[] va;
// delete lli;
}
iterator insert(const I& item) {
iterator pos = position(va, item);
lli.insert(pos.returnCurr(), item);
refresh(4);
return --pos;
}
iterator find(const I& item) const {
iterator start = iterator(va.at(binsearch(va, item)));
iterator end = iterator(va.at(binsearch(va, item)+1));
while(start != end) {
if(*start = item) {
return start;
}
else {
++start;
}
}
}
// void erase(iterator itr) {}
iterator begin() const {
lli.begin();
}
iterator end() const {
lli.end();
}
private:
int binsearch(const vector< DNode<I>* > vec, const I& item) const {
int left = 0;
int right = vec.size()-1;
while(left <= right) {
int mid = (left+right)/2;
iterator iter = iterator(vec.at(mid));
if(item < *iter) {
right = mid-1;
}
else if(item == *iter) {
return mid;
}
else {
left = mid+1;
}
}
return left;
}
iterator position(const vector< DNode<I>* > vec, const I& item) const {
iterator start = iterator(vec.at(binsearch(vec, item)));
iterator end = iterator(vec.at(binsearch(vec, item)+1));
while(start != end) {
if(*start < item) {
++start;
}
else {
return start;
}
}
}
void refresh(size_t newRatio) {
iterator iter = begin();
int count = 0;
va.clear();
while(iter!=end()) {
if(count % newRatio == 0) {
va.push_back(iter.returnCurr());
}
//push_backing the last node - to be added
iter++;
count++;
}
}
};
The class DList.h is very similar to the standard library list class.
Can you see the problem in my code?
Also, could you tell me if my code overall looks good or bad, in terms of both good programming practices and the implementation of the coding direction?
Thank you very much!
Look to me like you have a vector out of range on the first insert. insert calls position, which calls binsearch. binsearch returns 0 because the vector is empty, position then calls vector.at(0) (and vector.at(1)). Both of those are out of range errors because the vector is empty.
I'm just staring at the code so I might have made a mistake. Really you should use a debugger, and find out exactly where the problem occurs.
I'm trying (as an exercise) to create a simple numeric range class in C++. It will let you iterate through evenly spaced doubles (like the numpy/Python arange):
What I'd like to do (but with an iterator):
double lower = ..., upper = ..., delta = ...;
for (double val = lower; val < upper; val += delta)
{
// do something with val
f(val);
}
// include the last val to guarantee upper is included or exceeded
f(val); // do something with val
Desired equivalent iterator code:
double lower = ..., upper = ..., delta = ...;
NumericRange nr(lower, upper, delta);
for (NumericRange::const_iterator iter = nr.begin(); iter != nr.end(); iter++)
{
f(*iter);
}
I'd like my iterator to be compatible with STL iterators so I can reuse code (iterating through a NumericRange should be equivalent to iterating through std::vector).
I've had success simply storing the values in a std::vector (and then using the std::vector's iterator). This is how everything I've found online has solved this problem. However, it really isn't necessary to store the entire list.
Is there a way to avoid storing the entire set of values? Is there some iterable class I can inherit from and override ++, ==, etc. to get the desired effect without storing the std::vector<double>?
(I'd really like to know how to do this without BOOST, even though it's great. I'm asking this because I'd like to learn how to write (from scratch) something like a BOOST solution. I definitely know that part of software engineering is using the tools created by others, but I really want to learn how those tools are designed and built.)
My iterable NumericRange class (using std::vector<double> internally):
class NumericRange
{
protected:
double lower, upper, delta;
std::vector<double> sorted_range;
public:
typedef std::vector<double>::const_iterator const_iterator;
NumericRange()
{
lower = upper = delta = std::numeric_limits<double>::quiet_NaN();
// vector is constructed empty
}
NumericRange(double lower_param, double upper_param, double delta_param)
{
lower = lower_param;
upper = upper_param;
delta = delta_param;
assert(upper_param > lower_param);
double val;
// note: can be much faster without push_back
for (val = lower_param; val < upper_param; val += delta_param)
{
sorted_range.push_back(val);
}
// ensure the upper_value is contained or surpassed
sorted_range.push_back(val);
}
// to prevent comparison of the entire vector
bool operator ==(const NumericRange & rhs) const
{
return lower == rhs.lower && upper == rhs.upper && delta == rhs.delta;
}
// note: this class doesn't really need to store the values in a
// vector, but it makes the iterator interface much easier.
const_iterator begin() const
{
return sorted_range.begin();
}
const_iterator end() const
{
return sorted_range.end();
}
double get_lower() const
{
return lower;
}
double get_upper() const
{
return upper;
}
double get_delta() const
{
return delta;
}
size_t size() const
{
return sorted_range.size();
}
void print() const
{
std::cout << "[ " << lower << " : " << upper << ": +=" << delta << " ]" << std::endl;
}
};
Is there some iterable class I can inherit from and override ++, ==, etc. to get the desired effect without storing the std::vector<double>?
Yes, there is. Its name is std::iterator<std::input_iterator_tag, double>.
Here is a start for you, using int. To save space in my brain, I use the same class to represent both the range and the iterator.
#include <iterator>
#include <iostream>
struct NumericRange : public std::iterator< std::input_iterator_tag, int >
{
int current, fini, delta;
typedef NumericRange iterator;
typedef iterator const_iterator;
iterator begin() { return *this; }
iterator end() { return iterator(fini, fini, delta); }
iterator& operator++() { current += delta; return *this; }
iterator operator++(int) { iterator result(*this); ++*this; return result; }
int operator*() const { return current; }
NumericRange(int start, int fini, int delta)
: current(start), fini(fini), delta(delta)
{
}
bool operator==(const iterator& rhs) {
return rhs.current == current;
}
bool operator!=(const iterator& rhs) {
return !(*this == rhs);
}
};
void f(int i, int j) {
std::cout << i << " " << j << "\n";
}
int main () {
int lower = 4, upper = 14, delta = 5;
NumericRange nr(lower, upper, delta);
for (NumericRange::const_iterator iter = nr.begin(); iter != nr.end(); iter++)
{
f(*iter, *nr.end());
}
}
Based on the following question: Check if one string is a rotation of other string
I was thinking of making a cyclic iterator type that takes a range, and would be able to solve the above problem like so:
std::string s1 = "abc" ;
std::string s2 = "bca" ;
std::size_t n = 2; // number of cycles
cyclic_iterator it(s2.begin(),s2.end(),n);
cyclic_iterator end;
if (std::search(it, end, s1.begin(),s1.end()) != end)
{
std::cout << "s1 is a rotation of s2" << std::endl;
}
My question, Is there already something like this available? I've checked Boost and STL and neither have an exact implementation.
I've got a simple hand-written (derived from a std::forward_iterator_tag specialised version of std::iterator) one but would rather use an already made/tested implementation.
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 ) );
}
};
This should provide some ideas/solutions: 2 renditions, the second is a little lighter in weight. Both tested using a subrange of a vector and a list ...
#include <vector>
template <typename T, typename Container = std::vector<T>, typename Iterator = Container::iterator>
class RingIterator : public std::iterator <std::bidirectional_iterator_tag, T, ptrdiff_t>
{
Container& data;
Iterator cursor;
Iterator begin;
Iterator end;
public:
RingIterator (Container& v) : data(v), cursor(v.begin()), begin(v.begin()), end(v.end()) {}
RingIterator (Container& v, const Iterator& i) : data(v), cursor(i), begin(v.begin()), end(v.end()) {}
RingIterator (Container& v, const Iterator& i, const Iterator& j) : data(v), cursor(i), begin(i), end(j) {}
RingIterator (Container& v, size_t i) : data(v), cursor(v.begin() + i % v.size()), begin(v.begin()), end(v.end()) {}
bool operator == (const RingIterator& x) const
{
return cursor == x.cursor;
}
bool operator != (const RingIterator& x) const
{
return ! (*this == x);
}
reference operator*() const
{
return *cursor;
}
RingIterator& operator++()
{
++cursor;
if (cursor == end)
cursor = begin;
return *this;
}
RingIterator operator++(int)
{
RingIterator ring = *this;
++*this;
return ring;
}
RingIterator& operator--()
{
if (cursor == begin)
cursor = end;
--cursor;
return *this;
}
RingIterator operator--(int)
{
RingIterator ring = *this;
--*this;
return ring;
}
RingIterator insert (const T& x)
{
return RingIterator (data, data.insert (cursor, x));
}
RingIterator erase()
{
return RingIterator (data, data.erase (cursor));
}
};
template <typename T, typename Iterator>
class CyclicIterator : public std::iterator <std::bidirectional_iterator_tag, T, ptrdiff_t>
{
Iterator cursor;
Iterator begin;
Iterator end;
public:
CyclicIterator (const Iterator& i, const Iterator& j) : cursor(i), begin(i), end(j) {}
bool operator == (const CyclicIterator& x) const
{
return cursor == x.cursor;
}
bool operator != (const CyclicIterator& x) const
{
return ! (*this == x);
}
reference operator*() const
{
return *cursor;
}
CyclicIterator& operator++()
{
++cursor;
if (cursor == end)
cursor = begin;
return *this;
}
CyclicIterator operator++(int)
{
CyclicIterator ring = *this;
++*this;
return ring;
}
CyclicIterator& operator--()
{
if (cursor == begin)
cursor = end;
--cursor;
return *this;
}
CyclicIterator operator--(int)
{
CyclicIterator ring = *this;
--*this;
return ring;
}
};
#include <iostream>
#include <iomanip>
#include <list>
enum { CycleSize = 9, ContainerSize };
template <typename cyclicIterator>
void test (cyclicIterator& iterator, size_t mn)
{
int m = mn;
while (m--)
for (int n = mn; n--; ++iterator)
std::cout << std::setw(3) << *iterator << ' ';
--iterator;
m = mn;
while (m--)
for (int n = mn; n--; --iterator)
std::cout << std::setw(3) << *iterator << ' ';
}
template <typename containers>
void load (containers& container)
{
while (container.size() < ContainerSize)
container.push_back (container.size());
}
void main (void)
{
typedef std::vector<int> vContainer;
typedef vContainer::iterator vIterator;
typedef std::list<int> lContainer;
typedef lContainer::iterator lIterator;
vContainer v; load (v);
vIterator vbegin = v.begin() + 1;
RingIterator <int, vContainer, vIterator> vring (v, vbegin, v.end());
CyclicIterator <int, vIterator> vcycle (vbegin, v.end());
lContainer l; load (l);
lIterator lbegin = l.begin(); ++lbegin;
RingIterator <int, lContainer, lIterator> lring (l, lbegin, l.end());
CyclicIterator <int, lIterator> lcycle (lbegin, l.end());
test (vring, CycleSize);
test (vcycle, CycleSize);
test (lring, CycleSize);
test (lcycle, CycleSize);
}
The CGAL library defines Circulators. They are used like this.
template<class Circulator, class T>
bool contains(Circulator c, Circulator d, const T& value) {
if (c != 0) {
do {
if (*c == value)
return true;
} while (++c != d);
}
return false;
}
Note that they look like iterators at first glance but note that the logic (and the structure of the loop) is different than for iterators). if(not empty) do{..}while() instead of while(){...}.
Eric Niebler's ranges-v3 library (on which the upcoming C++20 ranges is based) has ranges::view::cycle. This adapts its source range into an endlessly repeating infinite range. However we require a single repeat which may be easily achieved using ranges::view::concat.
#include <ranges/v3/all.hpp>
int main() {
std::string s1 = "abc";
std::string s2 = "bca";
auto s2s2 = ranges::view::concat(s2, s2);
auto i = std::search(s2s2.begin(), s2s2.end(), s1.begin(), s1.end());
if (i != s2s2.end() && s1.size() == s2.size()) {
std::cout << "s1 is a rotation of s2\n";
}
}
You’re maybe looking for Boost’s Circular Buffer. But if you’ve already checked Boost, it might not be the one you want.
On the other hand, the very idea of cyclic iterator is not compatible to STL container ideology. You should not want cyclic iterator, as the user of this iterator may be surprized by its unusual behavior. Usually in STL you are iterating from the beginning to the end of container. Infinite loop in that case. Because the end is not reachable.
After all, obviously, you are not going to do more than 2 cycles to solve your task. No reason to have special iterator with confusing behavior. That is better to iterate usual linear container twice or may be even less then twice.