The following code example is taken from the book
C++ Templates - The Complete Guide, 2nd Edition
by David Vandevoorde, Nicolai M. Josuttis, and Douglas Gregor,
Addison-Wesley, 2017
© Copyright David Vandevoorde, Nicolai M. Josuttis, Douglas Gregor 2017
#include <iterator>
// implementation for random access iterators:
template<typename Iterator, typename Distance>
EnableIf<IsRandomAccessIterator<Iterator>>
advanceIter(Iterator& x, Distance n) {
x += n; // constant time
}
template<typename Iterator>
constexpr bool IsBidirectionalIterator =
IsConvertible<
typename std::iterator_traits<Iterator>::iterator_category,
std::bidirectional_iterator_tag>;
// implementation for bidirectional iterators:
template<typename Iterator, typename Distance>
EnableIf<IsBidirectionalIterator<Iterator> &&
!IsRandomAccessIterator<Iterator>>
advanceIter(Iterator& x, Distance n) {
if (n > 0) {
for ( ; n > 0; ++x, --n) { // linear time
}
} else {
for ( ; n < 0; --x, ++n) { // linear time
}
}
}
// implementation for all other iterators:
template<typename Iterator, typename Distance>
EnableIf<!IsBidirectionalIterator<Iterator>>
advanceIter(Iterator& x, Distance n) {
if (n < 0) {
throw "advanceIter(): invalid iterator category for negative n";
}
while (n > 0) { // linear time
++x;
--n;
}
}