Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#include <iostream>
#include <stddef.h>
namespace mozilla {
template<typename Iterator>
struct IteratorTraits
{
typedef typename Iterator::ValueType ValueType;
};
template<typename T>
struct IteratorTraits<T*>
{
typedef T ValueType;
};
template<typename T>
struct IteratorTraits<const T*>
{
typedef const T ValueType;
};
} // namespace mozilla
namespace mozilla {
template<typename IteratorT>
class ReverseIterator
{
public:
typedef typename IteratorTraits<IteratorT>::ValueType ValueType;
template<typename Iterator>
explicit ReverseIterator(Iterator aIter)
: mCurrent(aIter) { }
template<typename Iterator>
ReverseIterator(const ReverseIterator<Iterator>& aOther)
: mCurrent(aOther.mCurrent) { }
ValueType& operator*() const
{
IteratorT tmp = mCurrent;
return *--tmp;
}
/* Increments and decrements operators */
ReverseIterator& operator++() { --mCurrent; return *this; }
ReverseIterator& operator--() { ++mCurrent; return *this; }
ReverseIterator operator++(int) { auto ret = *this; mCurrent--; return ret; }
ReverseIterator operator--(int) { auto ret = *this; mCurrent++; return ret; }
/* Comparison operators */
template<typename Iterator1, typename Iterator2>
friend bool operator==(const ReverseIterator<Iterator1>& aIter1,
const ReverseIterator<Iterator2>& aIter2);
template<typename Iterator1, typename Iterator2>
friend bool operator!=(const ReverseIterator<Iterator1>& aIter1,
const ReverseIterator<Iterator2>& aIter2);
private:
IteratorT mCurrent;
};
template<typename Iterator1, typename Iterator2>
bool
operator==(const ReverseIterator<Iterator1>& aIter1,
const ReverseIterator<Iterator2>& aIter2)
{
return aIter1.mCurrent == aIter2.mCurrent;
}
template<typename Iterator1, typename Iterator2>
bool
operator!=(const ReverseIterator<Iterator1>& aIter1,
const ReverseIterator<Iterator2>& aIter2)
{
return aIter1.mCurrent != aIter2.mCurrent;
}
namespace detail {
template<typename IteratorT>
class IteratorRange
{
public:
typedef IteratorT iterator;
typedef IteratorT const_iterator;
typedef ReverseIterator<IteratorT> reverse_iterator;
typedef ReverseIterator<IteratorT> const_reverse_iterator;
template<typename Iterator1, typename Iterator2>
IteratorRange(Iterator1 aIterBegin, Iterator2 aIterEnd)
: mIterBegin(aIterBegin), mIterEnd(aIterEnd) { }
template<typename Iterator>
IteratorRange(const IteratorRange<Iterator>& aOther)
: mIterBegin(aOther.mIterBegin), mIterEnd(aOther.mIterEnd) { }
iterator begin() const { return mIterBegin; }
const_iterator cbegin() const { return begin(); }
iterator end() const { return mIterEnd; }
const_iterator cend() const { return end(); }
reverse_iterator rbegin() const { return reverse_iterator(mIterEnd); }
const_reverse_iterator crbegin() const { return rbegin(); }
reverse_iterator rend() const { return reverse_iterator(mIterBegin); }
const_reverse_iterator crend() const { return rend(); }
private:
IteratorT mIterBegin;
IteratorT mIterEnd;
};
} // namespace detail
template<typename Range>
detail::IteratorRange<typename Range::reverse_iterator>
Reversed(Range& aRange)
{
return {aRange.rbegin(), aRange.rend()};
}
template<typename Range>
detail::IteratorRange<typename Range::const_reverse_iterator>
Reversed(const Range& aRange)
{
return {aRange.rbegin(), aRange.rend()};
}
} // namespace mozilla
namespace mozilla {
namespace detail {
template<typename IntTypeT>
class IntegerIterator
{
public:
typedef const IntTypeT ValueType;
template<typename IntType>
explicit IntegerIterator(IntType aCurrent)
: mCurrent(aCurrent) { }
template<typename IntType>
IntegerIterator(const IntegerIterator<IntType>& aOther)
: mCurrent(aOther.mCurrent) { }
// Since operator* is required to return a reference, we return
// a reference to our member here.
const IntTypeT& operator*() const { return mCurrent; }
/* Increment and decrement operators */
IntegerIterator& operator++() { ++mCurrent; return *this; }
IntegerIterator& operator--() { --mCurrent; return *this; }
IntegerIterator operator++(int) { auto ret = *this; ++mCurrent; return ret; }
IntegerIterator operator--(int) { auto ret = *this; --mCurrent; return ret; }
/* Comparison operators */
template<typename IntType1, typename IntType2>
friend bool operator==(const IntegerIterator<IntType1>& aIter1,
const IntegerIterator<IntType2>& aIter2);
template<typename IntType1, typename IntType2>
friend bool operator!=(const IntegerIterator<IntType1>& aIter1,
const IntegerIterator<IntType2>& aIter2);
private:
IntTypeT mCurrent;
};
template<typename IntType1, typename IntType2>
bool operator==(const IntegerIterator<IntType1>& aIter1,
const IntegerIterator<IntType2>& aIter2)
{
return aIter1.mCurrent == aIter2.mCurrent;
}
template<typename IntType1, typename IntType2>
bool operator!=(const IntegerIterator<IntType1>& aIter1,
const IntegerIterator<IntType2>& aIter2)
{
return aIter1.mCurrent != aIter2.mCurrent;
}
template<typename IntTypeT>
class IntegerRange
{
public:
typedef IntegerIterator<IntTypeT> iterator;
typedef IntegerIterator<IntTypeT> const_iterator;
typedef ReverseIterator<IntegerIterator<IntTypeT>> reverse_iterator;
typedef ReverseIterator<IntegerIterator<IntTypeT>> const_reverse_iterator;
template<typename IntType>
explicit IntegerRange(IntType aEnd)
: mBegin(0), mEnd(aEnd) { }
template<typename IntType1, typename IntType2>
IntegerRange(IntType1 aBegin, IntType2 aEnd)
: mBegin(aBegin), mEnd(aEnd) { }
iterator begin() const { return iterator(mBegin); }
const_iterator cbegin() const { return begin(); }
iterator end() const { return iterator(mEnd); }
const_iterator cend() const { return end(); }
reverse_iterator rbegin() const { return reverse_iterator(mEnd); }
const_reverse_iterator crbegin() const { return rbegin(); }
reverse_iterator rend() const { return reverse_iterator(mBegin); }
const_reverse_iterator crend() const { return rend(); }
private:
IntTypeT mBegin;
IntTypeT mEnd;
};
} // namespace detail
template<typename IntType>
detail::IntegerRange<IntType>
MakeRange(IntType aEnd)
{
return detail::IntegerRange<IntType>(aEnd);
}
template<typename IntType1, typename IntType2>
detail::IntegerRange<IntType2>
MakeRange(IntType1 aBegin, IntType2 aEnd)
{
return detail::IntegerRange<IntType2>(aBegin, aEnd);
}
} // namespace mozilla
using namespace mozilla;
int main()
{
size_t n;
std::cin >> n;
for (auto i : Reversed(MakeRange(n))) {
std::cout << i << std::endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment