From 896e9d7a8a434484549b3362a568aba9b4a6a553 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Thu, 5 Jul 2018 23:00:29 +0200
Subject: [PATCH] iterator extensions improvements and documentation

---
 alib2std/src/extensions/iterator.hpp          | 379 +++++++++++++++---
 alib2std/test-src/extensions/IteratorTest.cpp |  34 ++
 alib2std/test-src/extensions/IteratorTest.h   |   2 +
 3 files changed, 370 insertions(+), 45 deletions(-)

diff --git a/alib2std/src/extensions/iterator.hpp b/alib2std/src/extensions/iterator.hpp
index 8ea3da5a27..70ded7e943 100644
--- a/alib2std/src/extensions/iterator.hpp
+++ b/alib2std/src/extensions/iterator.hpp
@@ -1,6 +1,22 @@
 /*
  * iterator.hpp
  *
+ * This file is part of Algorithms library toolkit.
+ * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz)
+
+ * Algorithms library toolkit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * Algorithms library toolkit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with Algorithms library toolkit.  If not, see <http://www.gnu.org/licenses/>.
+ *
  * Created on: Apr 1, 2013
  * Author: Jan Travnicek
  */
@@ -12,197 +28,470 @@
 
 namespace ext {
 
-template<class T>
+/**
+ * \brief
+ * Adaptor class to change begin and end behavior for reverse begin and reverse end and vise versa.
+ *
+ * \tparam T the type of class having rbegin and rend methods
+ */
+template < class T >
 class reverser {
+	/**
+	 * \brief
+	 * Reference holder for the adapted container.
+	 */
 	T & m_Container;
 
 public:
+	/**
+	 * \brief
+	 * Constructor of the adaptor class based on the adapted container.
+	 *
+	 * \param container the adapted container
+	 */
 	reverser ( T & container ) : m_Container ( container ) {
 	}
 
-	typename T::reverse_iterator begin ( ) const {
-		return m_Container.rbegin();
-	}
-
-	typename T::reverse_iterator end ( ) const {
-		return m_Container.rend();
-	}
-};
-
-template < class T >
-class reverser < const T > {
-	const T & m_Container;
-
-public:
-	reverser ( const T & container ) : m_Container ( container ) {
+	/**
+	 * \brief
+	 * Begin adaptor method to call rbegin.
+	 *
+	 * \return reverse begin iterator
+	 */
+	auto begin ( ) const {
+		return m_Container.rbegin ( );
 	}
 
-	typename T::const_reverse_iterator begin ( ) const {
-		return m_Container.rbegin();
+	/**
+	 * \brief
+	 * End adaptor method to call rend.
+	 *
+	 * \return reverse end iterator
+	 */
+	auto end ( ) const {
+		return m_Container.rend ( );
 	}
 
-	typename T::const_reverse_iterator end ( ) const {
-		return m_Container.rend();
-	}
 };
 
-template<class T>
-reverser<T> make_reverse(T& container) {
-	return reverser<T>(container);
+/**
+ * \brief
+ * Reverese adaptor construction function.
+ *
+ * \tparam T the type of class having rbegin and rend methods
+ *
+ * \param container the instance of an adapted class
+ *
+ * \return class having begin, end, other related methods swaping reverse and not reverse iterator getters
+ */
+template < class T >
+reverser < T > make_reverse ( T & container ) {
+	return reverser < T > ( container );
 }
 
+/**
+ * \brief
+ * Adaptor iterator to additionally call second dereference on the iterator dereference result.
+ *
+ * \tparam Iterator the adapted iterator
+ *
+ */
 template < class Iterator >
 class dereferencing_iterator {
+	/**
+	 * \brief
+	 * The value of the underlying iterator.
+	 */
 	Iterator m_base;
 
 public:
+	/**
+	 * \brief
+	 * The pointer type is the value of adapted iterator.
+	 */
 	using pointer = typename std::iterator_traits < Iterator >::value_type;
+
+	/**
+	 * \brief
+	 * The value type is the value of adapted iterator without pointer.
+	 */
 	using value_type = typename std::remove_pointer < pointer >::type;
+
+	/**
+	 * \brief
+	 * Difference_type is inherited.
+	 */
 	using difference_type = std::ptrdiff_t;
+
+	/**
+	 * \brief
+	 * Reference type is reference to the value type.
+	 */
 	using reference = value_type &;
+
+	/**
+	 * \brief
+	 * iterator_category is inherited.
+	 */
 	using iterator_category = typename std::iterator_traits < Iterator >::iterator_category;
 
+	/**
+	 * \brief
+	 * Constructor of the dereferencing iterator adaptor.
+	 *
+	 * \param base the underlying iterator
+	 */
 	explicit dereferencing_iterator ( Iterator base ) : m_base ( base ) {
 	}
 
+	/**
+	 * Cast constructor from dereferencing iterator adapting compatible iterator.
+	 *
+	 * \tparam Iter the underlying iterator type of dereference iterator
+	 *
+	 * \param iter the casted dereferencing iterator
+	 */
 	template < class Iter >
 	dereferencing_iterator ( const dereferencing_iterator < Iter > & iter ) : m_base ( iter.base ( ) ) {
 	}
 
-	// Dereferencable.
+	/**
+	 * \brief
+	 * Dereference operator doing extra dereference.
+	 *
+	 * \return the value pointed to by result of dereference of the underlying iterator
+	 */
 	reference operator * ( ) const {
 		return * * m_base;
 	}
 
+	/**
+	 * \brief
+	 * Arrow operator doing extra dereference.
+	 *
+	 * \return dereference of the underlying iterator
+	 */
 	pointer operator -> ( ) const {
 		return * m_base;
 	}
 
-	// Pre- and post-incrementable.
+	/**
+	 * \brief
+	 * Increment operator.
+	 *
+	 * Increments the underlying operator.
+	 *
+	 * \return the modified iterator
+	 */
 	dereferencing_iterator < Iterator > & operator ++ ( ) {
 		++ m_base;
 		return * this;
 	}
 
+	/**
+	 * \brief
+	 * Increment operator.
+	 *
+	 * Increments the underlying operator.
+	 *
+	 * \return the original iterator
+	 */
 	dereferencing_iterator < Iterator > operator ++ ( int ) {
 		auto tmp = * this;
 		++ m_base;
 		return tmp;
 	}
 
-	// Pre- and post-decrementable.
+	/**
+	 * \brief
+	 * Decrement operator.
+	 *
+	 * Decrements the underlying operator.
+	 *
+	 * \return the modified iterator
+	 */
 	dereferencing_iterator < Iterator > & operator -- ( ) {
 		++ m_base;
 		return * this;
 	}
 
+	/**
+	 * \brief
+	 * Decrement operator.
+	 *
+	 * Decrements the underlying operator.
+	 *
+	 * \return the original iterator
+	 */
 	dereferencing_iterator < Iterator > operator -- ( int ) {
 		auto tmp = * this;
 		++ m_base;
 		return tmp;
 	}
 
-	// Add and substract.
+	/**
+	 * \brief
+	 * Shifs the iterator by \p distance.
+	 *
+	 * \param distance the distance to shift by
+	 *
+	 * \return the modified iterator
+	 */
 	dereferencing_iterator < Iterator > & operator += ( int distance ) {
 		m_base += distance;
 		return *this;
 	}
 
+	/**
+	 * \brief
+	 * Creates a new iterator and shifs it by \p distance.
+	 *
+	 * \param distance the distance to shift by
+	 *
+	 * \return the new iterator
+	 */
 	dereferencing_iterator < Iterator > operator + ( int distance ) const {
 		auto res = * this;
 		res += distance;
 		return res;
 	}
 
+	/**
+	 * \brief
+	 * Shifs the iterator back by \p distance.
+	 *
+	 * \param distance the distance to shift by
+	 *
+	 * \return the modified iterator
+	 */
 	dereferencing_iterator < Iterator > & operator -= ( int distance ) {
 		m_base -= distance;
 		return *this;
 	}
 
+	/**
+	 * \brief
+	 * Creates a new iterator and shifs it back by \p distance.
+	 *
+	 * \param distance the distance to shift by
+	 *
+	 * \return the new iterator
+	 */
 	dereferencing_iterator < Iterator > operator - ( int distance ) const {
 		auto res = * this;
 		res -= distance;
 		return res;
 	}
 
-	//Array subscript
+	/**
+	 * \brief
+	 * Array subscript operator.
+	 *
+	 * Additionaly dereferences the result of subscript of the underlying iterator.
+	 *
+	 * \param index the subscript index
+	 *
+	 * \return the value pointed to by pointer at position given by \p index
+	 */
 	reference operator [ ] ( int index ) const {
 		return * ( m_base [ index ] );
 	}
 
+	/**
+	 * \brief
+	 * Distance of two iterators computation operator.
+	 *
+	 * \param other the other iterator
+	 *
+	 * \return the distance between this and the other iterator
+	 */
 	difference_type operator - ( const dereferencing_iterator < Iterator > & other ) {
 		return m_base - other.m_base;
 	}
 
-	// Equality / inequality.
+	/**
+	 * \brief
+	 * Comparison of iterators for equality.
+	 *
+	 * \param other the other iterator
+	 *
+	 * \return true if the two iterators underlying iterators are equal
+	 */
 	bool operator == ( const dereferencing_iterator < Iterator > & other ) const {
 		return this->m_base == other.m_base;
 	}
 
+	/**
+	 * \brief
+	 * Comparison of iterators for non-equality.
+	 *
+	 * \param other the other iterator
+	 *
+	 * \return true if the two iterators underlying iterators are not equal
+	 */
 	bool operator != ( const dereferencing_iterator < Iterator > & other ) const {
 		return ! ( * this == other );
 	}
 
+	/**
+	 * \brief
+	 * Less than comparison of iterators.
+	 *
+	 * \param other the other iterator
+	 *
+	 * \return true if the underlying iterator of this is less than the underlying iterator of the other one
+	 */
 	bool operator < ( const dereferencing_iterator < Iterator > & other ) const {
 		return this->m_base < other.m_base;
 	}
 
+	/**
+	 * \brief
+	 * Greater than comparison of iterators.
+	 *
+	 * \param other the other iterator
+	 *
+	 * \return true if the underlying iterator of this is greater than the underlying iterator of the other one
+	 */
 	bool operator > ( const dereferencing_iterator < Iterator > & other ) const {
 		return other < * this;
 	}
 
+	/**
+	 * \brief
+	 * Less than or equal comparison of iterators.
+	 *
+	 * \param other the other iterator
+	 *
+	 * \return true if the underlying iterator of this is less than or equal to the underlying iterator of the other one
+	 */
 	bool operator <= ( const dereferencing_iterator < Iterator > & other ) const {
 		return ! ( * this > other );
 	}
 
+	/**
+	 * \brief
+	 * Greater than or equal comparison of iterators.
+	 *
+	 * \param other the other iterator
+	 *
+	 * \return true if the underlying iterator of this is greater than or equal to the underlying iterator of the other one
+	 */
 	bool operator >= ( const dereferencing_iterator < Iterator > & other ) const {
 		return ! ( * this < other );
 	}
 
+	/**
+	 * \brief
+	 * The underlying iterator getter.
+	 *
+	 * \return the underlying iterator
+	 */
 	Iterator base ( ) const {
 		return m_base;
 	}
 
 };
 
+/**
+ * \brief
+ * Dereferencing adaptor construction function.
+ *
+ * \tparam T the type of iterator to adapt
+ *
+ * \param iter source iterator for inner dereferencing
+ *
+ * \return adapted iterator
+ */
 template < class Iterator >
 dereferencing_iterator < Iterator > dereferencer ( Iterator iter ) {
 	return dereferencing_iterator < Iterator > ( iter );
 }
 
+/**
+ * \brief
+ * False case type trait detecting the template parameter T is not an iterator.
+ *
+ * The class has a field value set to false.
+ */
 template < typename T >
 struct is_iterator : std::false_type {};
 
+/**
+ * \brief
+ * True case type trait detecting the template parameter T is an iterator.
+ *
+ * The class has a field value set to true.
+ */
 template < typename T >
 struct is_iterator<typename std::iterator_traits<T>> : std::true_type {};
 
-template < typename BidirectionalIterator, typename Distance >
-inline constexpr void retractInternal ( BidirectionalIterator & i, Distance n, std::bidirectional_iterator_tag ) {
-	while ( n -- )
-		-- i;
+/**
+ * Implementation of retract function specific to input iterators.
+ *
+ * \tparam Iterator the type of retracted iterator
+ * \tparam Distance the type of distance to retract
+ *
+ * \param i the retracted iterator
+ * \param n the distance to retract
+ */
+template < typename InputIterator, typename Distance >
+inline constexpr void retractInternal ( InputIterator & i, Distance n, std::input_iterator_tag ) {
+	assert ( n <= 0 );
 	while ( n ++ )
 		++ i;
 }
 
+/**
+ * Implementation of retract function specific to bidrectional iterators.
+ *
+ * \tparam Iterator the type of retracted iterator
+ * \tparam Distance the type of distance to retract
+ *
+ * \param i the retracted iterator
+ * \param n the distance to retract
+ */
+template < typename BidirectionalIterator, typename Distance >
+inline constexpr void retractInternal ( BidirectionalIterator & i, Distance n, std::bidirectional_iterator_tag ) {
+	if ( n > 0)
+		while ( n -- )
+			-- i;
+	else
+		while ( n ++ )
+			++ i;
+}
+
+/**
+ * Implementation of retract function specific to random access iterators.
+ *
+ * \tparam Iterator the type of retracted iterator
+ * \tparam Distance the type of distance to retract
+ *
+ * \param i the retracted iterator
+ * \param n the distance to retract
+ */
 template < typename RandomAccessIterator, typename Distance >
 inline constexpr void retractInternal ( RandomAccessIterator & i, Distance n, std::random_access_iterator_tag ) {
-	i += n;
+	i -= n;
 }
 
 /**
- *  \brief A generalization of pointer arithmetic.
- *  \param i A bidirectional iterator.
- *  \param n The \a delta by which to change \p i.
+ * \brief A generalization of pointer arithmetic.
  *
- *  This decrements \p i by \p n. For bidirectional and random access
- *  iterators, \p n may be negative, in which case \p i is incremented.
+ * \tparam Iterator the type of retracted iterator
+ * \tparam Distance the type of distance to retract
  *
- *  For random access iterators, this uses their \c + and \c - operations
- *  and are constant time. For other %iterator classes they are linear time.
+ * \param i An instance of some iterator.
+ * \param n The \a delta by which to change \p i.
+ *
+ * For random access and bidirectional iterators, \p n may be positive, in which case \p i is decremented.
+ * For random access, bidirectional, and input iterators, \p n may be negative, in which case \p i is incremented.
+ *
+ * For random access iterators, this uses their \c + and \c - operations and are constant time. For other %iterator classes they are linear time.
  */
-template < typename BidirectionalIterator, typename Distance >
-inline constexpr void retract ( BidirectionalIterator & i, Distance n ) {
-	typename std::iterator_traits < BidirectionalIterator >::difference_type d = n;
+template < typename Iterator, typename Distance >
+inline constexpr void retract ( Iterator & i, Distance n ) {
+	typename std::iterator_traits < Iterator >::difference_type d = n;
 	retractInternal ( i, d, std::__iterator_category ( i ) );
 }
 
diff --git a/alib2std/test-src/extensions/IteratorTest.cpp b/alib2std/test-src/extensions/IteratorTest.cpp
index 322b11f0b4..ac11e103d2 100644
--- a/alib2std/test-src/extensions/IteratorTest.cpp
+++ b/alib2std/test-src/extensions/IteratorTest.cpp
@@ -35,3 +35,37 @@ void IteratorTest::testIterator() {
 	}
 }
 
+void IteratorTest::testReverser() {
+	std::vector < int > data;
+
+	data.push_back ( 1 );
+	data.push_back ( 2 );
+	data.push_back ( 3 );
+	data.push_back ( 4 );
+	data.push_back ( 5 );
+
+	std::vector < int > data2;
+
+	data2.push_back ( 5 );
+	data2.push_back ( 4 );
+	data2.push_back ( 3 );
+	data2.push_back ( 2 );
+	data2.push_back ( 1 );
+
+	std::vector < int > trans;
+
+	for ( int elem : ext::make_reverse ( data ) ) {
+		trans.push_back ( elem );
+	}
+
+	CPPUNIT_ASSERT ( data2 == trans );
+
+	const std::vector < int > & dataRef = data;
+	trans.clear ( );
+
+	for ( int elem : ext::make_reverse ( dataRef ) ) {
+		trans.push_back ( elem );
+	}
+
+	CPPUNIT_ASSERT ( data2 == trans );
+}
diff --git a/alib2std/test-src/extensions/IteratorTest.h b/alib2std/test-src/extensions/IteratorTest.h
index de71abdc18..1cff4cd97e 100644
--- a/alib2std/test-src/extensions/IteratorTest.h
+++ b/alib2std/test-src/extensions/IteratorTest.h
@@ -7,6 +7,7 @@ class IteratorTest : public CppUnit::TestFixture
 {
   CPPUNIT_TEST_SUITE( IteratorTest );
   CPPUNIT_TEST( testIterator );
+  CPPUNIT_TEST( testReverser );
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -14,6 +15,7 @@ public:
   void tearDown();
 
   void testIterator();
+  void testReverser();
 };
 
 #endif  // ITERATOR_TEST_H_
-- 
GitLab