#include <iterator>
#include <stdexcept>
template <class Range> class MultiRangeIterator;
template <class Iterator, class SubRange>
struct MultiRange;
template <class E> struct EmptyRange
{
typedef MultiRangeIterator<EmptyRange<E>> iterator;
iterator begin();
iterator end();
template <class NewIter>
struct Append
{
typedef MultiRange<NewIter, EmptyRange<E>> type;
};
template <class NewIter>
typename Append<NewIter>::type append(NewIter first, NewIter last) const;
};
template <class Iterator, class SubRange = EmptyRange<typename Iterator::value_type>>
struct MultiRange
{
Iterator first;
Iterator last;
SubRange deeper;
template <class NewIter>
struct Append {
typedef MultiRange<Iterator, typename SubRange::template Append<NewIter>::type> type;
};
typedef MultiRangeIterator<MultiRange> iterator;
MultiRange(Iterator a, Iterator b, SubRange s = SubRange())
: first(a), last(b), deeper(s) {}
iterator begin();
iterator end();
template <class NewIter>
typename Append<NewIter>::type operator()(NewIter newFirst, NewIter newLast) const
{ return this->append(newFirst, newLast); }
template <class NewIter>
typename Append<NewIter>::type append(NewIter newFirst, NewIter newLast) const
{
typedef typename Append<NewIter>::type NewMultiRange;
return NewMultiRange(first, last, deeper.append(newFirst, newLast));
}
};
template <class E>
template <class NewIter>
typename EmptyRange<E>::template Append<NewIter>::type EmptyRange<E>::append(NewIter first, NewIter last) const
{
return MultiRange<NewIter,EmptyRange<E>>(first, last);
}
template <class Iterator>
MultiRange<Iterator> makeRange(Iterator first, Iterator last)
{ return MultiRange<Iterator> (first, last); }
template <class E>
struct MultiRangeIterator<EmptyRange<E>>
{
E& operator*() const { throw std::out_of_range("past the end!"); }
MultiRangeIterator& operator++() { return *this; }
};
template <class Iterator, class SubRange>
struct MultiRangeIterator<MultiRange<Iterator, SubRange>>
{
MultiRange<Iterator, SubRange> const& myRange;
Iterator myIter;
MultiRangeIterator<SubRange> deeperIter;
typedef typename std::iterator_traits<Iterator>::reference reference;
MultiRangeIterator(MultiRange<Iterator, SubRange> const& r, Iterator it, MultiRangeIterator<SubRange> d )
: myRange(r), myIter(it), deeperIter(d) {}
bool pastEndOfRange() const
{ return myIter == myRange.last; }
reference operator*() const
{ return pastEndOfRange() ?
*deeperIter :
*myIter; }
MultiRangeIterator& operator++()
{
if (!pastEndOfRange())
++myIter;
else
++deeperIter;
return *this;
}
};
namespace std {
template <class Iterator, class SubRange>
struct iterator_traits<MultiRangeIterator<MultiRange<Iterator, SubRange>>>
: std::iterator_traits<Iterator>
{};
};
template <class Iterator, class SubRange>
bool operator== (MultiRangeIterator<MultiRange<Iterator, SubRange>> const& lhs,
MultiRangeIterator<MultiRange<Iterator, SubRange>> const& rhs)
{ return lhs.myIter == rhs.myIter && lhs.deeperIter == rhs.deeperIter; }
template <class E>
bool operator == (MultiRangeIterator<EmptyRange<E>> const& lhs,
MultiRangeIterator<EmptyRange<E>> const& rhs)
{ return true; }
template <class Range>
bool operator != (MultiRangeIterator<Range> const& lhs, MultiRangeIterator<Range> const& rhs)
{ return !(lhs==rhs); }
template <class Iterator, class SubRange>
typename MultiRange<Iterator, SubRange>::iterator
MultiRange<Iterator, SubRange>::begin()
{ return iterator(*this, first, deeper.begin()); }
template <class Iterator, class SubRange>
typename MultiRange<Iterator, SubRange>::iterator
MultiRange<Iterator, SubRange>::end()
{ return iterator(*this, last, deeper.end()); }
template <class E>
typename EmptyRange<E>::iterator
EmptyRange<E>::begin()
{ return iterator(); }
template <class E>
typename EmptyRange<E>::iterator
EmptyRange<E>::end()
{ return iterator(); }
#include <vector>
#include <list>
#include <set>
#include <iostream>
#include <string>
#include <sstream>
#include <iterator>
/* nur zu Testzwecken...
template <class E>
char const* debug(MultiRangeIterator<EmptyRange<E>>) {return "()";}
template <class Iterator, class SubRange>
std::string debug(MultiRangeIterator<MultiRange<Iterator, SubRange>> const& mri)
{
std::ostringstream out;
out << '(' << std::distance(mri.myRange.first, mri.myIter);
if (mri.pastEndOfRange()) out << "=end";
out << debug(mri.deeperIter) << ')';
return out.str();
} */
using namespace std;
int main()
{
vector<int> vi = {1,2,3,4};
list<int> li = {5,6,7,8};
list<int> li2 = {9,10};
auto myRange = makeRange(vi.begin(), vi.end())
(li.begin(), li.end());
auto newRange = myRange.append(myRange.begin(), myRange.end())
(li2.begin(), li2.end());
for(auto it = newRange.begin(); it != newRange.end(); ++it)
{
// cout << debug(it) << ": ";
cout << *it << ',';
}
}