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