#include <iterator>
template<class iterator>
typename std::iterator_traits<iterator>::pointer struct_deref(iterator it)
{return it.operator->();}
template<class T>
T* struct_deref(T* it)
{return it;}
template<class underlying_type>
struct back_and_forth_iterator {
typedef back_and_forth_iterator bnfit;
typedef typename std::iterator_traits<underlying_type>::value_type value_type;
typedef typename std::iterator_traits<underlying_type>::difference_type difference_type;
typedef typename std::iterator_traits<underlying_type>::pointer pointer;
typedef typename std::iterator_traits<underlying_type>::reference reference;
typedef typename std::iterator_traits<underlying_type>::reference iterator_category;
typedef size_t size_type;
back_and_forth_iterator()
:underlying(), turnaround(), forward(true) {}
back_and_forth_iterator(underlying_type pos, underlying_type turn, bool fwd)
:underlying(pos), turnaround(turn), forward(fwd) {}
back_and_forth_iterator(const bnfit& rhs)
:underlying(rhs.underlying), turnaround(rhs.turnaround), forward(rhs.forward) {}
~back_and_forth_iterator()
{}
bnfit& operator=(const bnfit& rhs)
{underlying=rhs.underlying; forward=rhs.forward; return *this;}
bnfit& operator++()
{
if (forward) {
if (++underlying == turnaround)
forward = false;
} else
--underlying;
return *this;
}
bnfit operator++(int)
{bnfit p(*this); operator++(); return p;}
bnfit& operator--()
{
if (!forward) {
if (--underlying == turnaround)
forward = true;
} else
++underlying;
return *this;
}
bnfit operator--(int)
{bnfit p(*this); operator--(); return p;}
bnfit& operator+=(size_type o)
{
if (forward) {
size_type m = std::min(turnaround-underlying, o);
underlying += m;
o -= m;
}
underlying -= o;
return *this;
}
friend bnfit operator+(const bnfit& it, size_type o)
{return bnfit(it)+=o;}
friend bnfit operator+(size_type o, const bnfit& it)
{return bnfit(it)+=o;}
bnfit& operator-=(size_type o)
{
if (!forward) {
size_type m = std::min(turnaround-underlying, o);
underlying += m;
o -= m;
}
underlying -= o;
return *this;
}
friend bnfit operator-(const bnfit& it, size_type o)
{return bnfit(it)-=o;}
friend difference_type operator-(bnfit lhs, bnfit rhs)
{
if(lhs.forward) {
if (rhs.forward)
return lhs.underlying - rhs.underlying;
else
return lhs.underlying-lhs.turnaround + rhs.underlying-rhs.turnaround;
} else {
if (rhs.forward)
return lhs.turnaround-lhs.underlying + rhs.turnaround-rhs.underlying;
else
return rhs.underlying - lhs.underlying;
}
}
reference operator*() const
{
if (forward) return *underlying;
else return *std::prev(underlying);
}
pointer operator->() const
{
if (forward) return struct_deref(underlying);
else return struct_deref(std::prev(underlying));
}
reference operator[](size_type o) const
{return *(iterator(*this)+=o);}
friend bool operator==(const bnfit& lhs, const bnfit& rhs)
{return lhs.underlying==rhs.underlying && lhs.forward==rhs.forward;}
friend bool operator!=(const bnfit& lhs, const bnfit& rhs)
{return lhs.underlying!=rhs.underlying || lhs.forward!=rhs.forward;}
friend bool operator<(const bnfit& lhs, const bnfit& rhs)
{return compare(lhs, rhs)<0;}
friend bool operator>(const bnfit& lhs, const bnfit& rhs)
{return compare(lhs, rhs)>0;}
friend bool operator<=(const bnfit& lhs, const bnfit& rhs)
{return compare(lhs, rhs)<=0;}
friend bool operator>=(const bnfit& lhs, const bnfit& rhs)
{return compare(lhs, rhs)>=0;}
friend void swap(const bnfit& lhs, const bnfit& rhs)
{
using std::swap;
swap(lhs.underlying, rhs.underlying);
swap(lhs.turnaround, rhs.turnaround),
swap(lhs.foward, rhs.forward);
}
private:
static int compare(const bnfit& lhs, const bnfit& rhs)
{
int flip = (lhs.forward ? 1 : -1);
if (lhs.forward != rhs.forward) return -1*flip;
if (lhs.underlying<rhs.underlying) return -1*flip;
if (rhs.underlying<lhs.underlying) return flip;
return 0;
}
underlying_type underlying;
underlying_type turnaround;
bool forward;
};
template<class underlying_type>
back_and_forth_iterator<underlying_type> make_backforth_first(underlying_type first, underlying_type last)
{return back_and_forth_iterator<underlying_type>(first, last, true);}
template<class underlying_type>
back_and_forth_iterator<underlying_type> make_backforth_last(underlying_type first, underlying_type last)
{return back_and_forth_iterator<underlying_type>(first, last, false);}
#include <string>
#include <iostream>
#include <list>
int main() {
std::string s("qwew");
auto first0 = make_backforth_first(s.begin(), s.end());
auto last0 = make_backforth_last(s.begin(), s.end());
for (auto it=first0; it!=last0; ++it)
std::cout << *it << ' ';
std::cout << std::endl;
std::list<std::string> l;
l.push_back(s);
auto first1 = make_backforth_first(l.begin(), l.end());
auto last1 = make_backforth_last(l.begin(), l.end());
for (auto it=first1; it!=last1; ++it)
std::cout << *it << ' ';
std::cout << std::endl;
}