diff --git a/alib2std/src/extensions/iterator.hpp b/alib2std/src/extensions/iterator.hpp index 46694aaa0709bcdfa4c1c0e21de984c7af6c1fd8..1b2f482d7f2fcdead33179d9e9fb981b08faf6f9 100644 --- a/alib2std/src/extensions/iterator.hpp +++ b/alib2std/src/extensions/iterator.hpp @@ -34,6 +34,125 @@ reverser<T> make_reverse(T& container) { return reverser<T>(container); } +template < class Iterator > +class dereferencing_iterator { + Iterator m_base; + +public: + using pointer = typename std::iterator_traits < Iterator >::value_type; + using value_type = typename std::remove_pointer < pointer >::type; + using difference_type = std::ptrdiff_t; + using reference = value_type &; + using iterator_category = typename std::iterator_traits < Iterator >::iterator_category; + + explicit dereferencing_iterator ( Iterator base ) : m_base ( base ) { + } + + template < class Iter > + dereferencing_iterator ( const dereferencing_iterator < Iter > & iter ) : m_base ( iter.base ( ) ) { + } + + // Dereferencable. + reference operator * ( ) const { + return * * m_base; + } + + pointer operator -> ( ) const { + return * m_base; + } + + // Pre- and post-incrementable. + dereferencing_iterator < Iterator > & operator ++ ( ) { + ++ m_base; + return * this; + } + + dereferencing_iterator < Iterator > operator ++ ( int ) { + auto tmp = * this; + ++ m_base; + return tmp; + } + + // Pre- and post-decrementable. + dereferencing_iterator < Iterator > & operator -- ( ) { + ++ m_base; + return * this; + } + + dereferencing_iterator < Iterator > operator -- ( int ) { + auto tmp = * this; + ++ m_base; + return tmp; + } + + // Add and substract. + dereferencing_iterator < Iterator > & operator += ( int distance ) { + m_base += distance; + return *this; + } + + dereferencing_iterator < Iterator > operator + ( int distance ) const { + auto res = * this; + res += distance; + return res; + } + + dereferencing_iterator < Iterator > & operator -= ( int distance ) { + m_base -= distance; + return *this; + } + + dereferencing_iterator < Iterator > operator - ( int distance ) const { + auto res = * this; + res -= distance; + return res; + } + + //Array subscript + reference operator [ ] ( int index ) const { + return * ( m_base [ index ] ); + } + + difference_type operator - ( const dereferencing_iterator < Iterator > & other ) { + return m_base - other.m_base; + } + + // Equality / inequality. + bool operator == ( const dereferencing_iterator < Iterator > & other ) const { + return this->m_base == other.m_base; + } + + bool operator != ( const dereferencing_iterator < Iterator > & other ) const { + return ! ( * this == other ); + } + + bool operator < ( const dereferencing_iterator < Iterator > & other ) const { + return this->m_base < other.m_base; + } + + bool operator > ( const dereferencing_iterator < Iterator > & other ) const { + return other < * this; + } + + bool operator <= ( const dereferencing_iterator < Iterator > & other ) const { + return ! ( * this > other ); + } + + bool operator >= ( const dereferencing_iterator < Iterator > & other ) const { + return ! ( * this < other ); + } + + Iterator base ( ) const { + return m_base; + } + +}; + +template < class Iterator > +dereferencing_iterator < Iterator > dereferencer ( Iterator iter ) { + return dereferencing_iterator < Iterator > ( iter ); +} + template < typename T > struct is_iterator : std::false_type {}; diff --git a/alib2std/test-src/extensions/IteratorTest.cpp b/alib2std/test-src/extensions/IteratorTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..322b11f0b4ffdae59887862ec9abfdb5b01c6e45 --- /dev/null +++ b/alib2std/test-src/extensions/IteratorTest.cpp @@ -0,0 +1,37 @@ +#include "IteratorTest.h" +#include <alib/set> +#include <alib/vector> +#include <alib/pair> +#include <sstream> +#include <alib/istream> +#include <alib/string> +#include <alib/iterator> + +CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( IteratorTest, "bits" ); +CPPUNIT_TEST_SUITE_REGISTRATION( IteratorTest ); + +void IteratorTest::setUp() { +} + +void IteratorTest::tearDown() { +} + +void IteratorTest::testIterator() { + std::vector < int * > data; + + data.push_back ( new int ( 1 ) ); + data.push_back ( new int ( 2 ) ); + data.push_back ( new int ( 3 ) ); + data.push_back ( new int ( 4 ) ); + data.push_back ( new int ( 5 ) ); + + std::vector < int > ref { 1, 2, 3, 4, 5 }; + + bool res = std::equal ( ext::dereferencer ( data.begin ( ) ), ext::dereferencer ( data.end ( ) ), ref.begin ( ), ref.end ( ) ); + CPPUNIT_ASSERT ( res ); + + for ( int * elem : data ) { + delete elem; + } +} + diff --git a/alib2std/test-src/extensions/IteratorTest.h b/alib2std/test-src/extensions/IteratorTest.h new file mode 100644 index 0000000000000000000000000000000000000000..de71abdc1868a00af6872f66f7f19f9e4a4a67b6 --- /dev/null +++ b/alib2std/test-src/extensions/IteratorTest.h @@ -0,0 +1,19 @@ +#ifndef ITERATOR_TEST_H_ +#define ITERATOR_TEST_H_ + +#include <cppunit/extensions/HelperMacros.h> + +class IteratorTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( IteratorTest ); + CPPUNIT_TEST( testIterator ); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testIterator(); +}; + +#endif // ITERATOR_TEST_H_