From 0da7bfd5fb386d0613f21f2fee5aa8641bbd8832 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 13 Mar 2019 09:05:11 +0100
Subject: [PATCH] reverse iterator in ptr_vector::insert, ... and
 ptr_array::set, ...

---
 .../src/extensions/container/ptr_array.hpp    |  36 ++
 .../src/extensions/container/ptr_vector.hpp   | 447 +++++++++++++++++-
 .../extensions/container/PtrVectorTest.cpp    |   5 +
 3 files changed, 484 insertions(+), 4 deletions(-)

diff --git a/alib2std/src/extensions/container/ptr_array.hpp b/alib2std/src/extensions/container/ptr_array.hpp
index f2f901f4c0..60402c3005 100644
--- a/alib2std/src/extensions/container/ptr_array.hpp
+++ b/alib2std/src/extensions/container/ptr_array.hpp
@@ -551,6 +551,25 @@ public:
 		return dereferencer ( m_data.begin ( ) + dist );
 	}
 
+	/**
+	 * \brief
+	 * Setter of value in the array on position specified by iterator specified by \p pos. The value is cloned from the \p value.
+	 *
+	 * \param pos the iterator specifying position to set
+	 * \param value the value to place at given position
+	 *
+	 * \return iterator to the set value
+	 */
+	template < class R >
+	iterator set ( const_reverse_iterator pos, R && value ) {
+		size_type dist = std::distance ( crbegin ( ), pos );
+
+		// If the set value and value at position pos are same instances first clone, then delete
+		delete std::exchange ( m_data.at ( m_data.size ( ) - dist - 1 ), ext::clone ( std::forward < R > ( value ) ) );
+
+		return dereferencer ( m_data.rbegin ( ) + dist );
+	}
+
 	/**
 	 * \brief
 	 * Setter of internaly constructed value into the array on position specified by iterator specified by \p pos. The value is constructed from paramter pack.
@@ -568,6 +587,23 @@ public:
 		return set ( pos, R ( std::forward < Args > ( args ) ... ) );
 	}
 
+	/**
+	 * \brief
+	 * Setter of internaly constructed value into the array on position specified by iterator specified by \p pos. The value is constructed from paramter pack.
+	 *
+	 * \tparam R the actual type of constructed value
+	 * \tparam Args ... types of value constructor parameters
+	 *
+	 * \param pos the iterator specifying position to set
+	 * \param args ... value constructor parameters
+	 *
+	 * \return iterator to the set value
+	 */
+	template < class R, class ... Args >
+	iterator emplace_set ( const_reverse_iterator pos, Args && ... args ) {
+		return set ( pos, R ( std::forward < Args > ( args ) ... ) );
+	}
+
 	/**
 	 * Swaps two instances of pointer array
 	 *
diff --git a/alib2std/src/extensions/container/ptr_vector.hpp b/alib2std/src/extensions/container/ptr_vector.hpp
index 3a1f1bf573..f096aa61e3 100644
--- a/alib2std/src/extensions/container/ptr_vector.hpp
+++ b/alib2std/src/extensions/container/ptr_vector.hpp
@@ -24,7 +24,6 @@
 #ifndef __PTR_VECTOR_HPP_
 #define __PTR_VECTOR_HPP_
 
-#include <vector>
 #include <ostream>
 #include <sstream>
 #include <string>
@@ -33,6 +32,7 @@
 #include <extensions/allocFix.hpp>
 #include <extensions/range.hpp>
 #include <extensions/clone.hpp>
+#include <extensions/container/vector.hpp>
 
 namespace ext {
 
@@ -49,7 +49,7 @@ class ptr_vector {
 	 * \brief
 	 * The vector of pointers to stored values
 	 */
-	std::vector < T * > m_data;
+	ext::vector < T * > m_data;
 
 public:
 	/**
@@ -622,6 +622,22 @@ public:
 		m_data.clear ( );
 	}
 
+	/**
+	 * \brief
+	 * Changes the value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 *
+	 * \param pos the position to set
+	 * \param value the value to place to that position
+	 *
+	 * \return updated iterator to the changed location
+	 */
+	template < class R >
+	iterator set ( iterator pos, R && value ) {
+		return set ( const_iterator ( pos ), std::forward < R > ( value ) );
+	}
+
 	/**
 	 * \brief
 	 * Changes the value on position given by iterator \p pos
@@ -643,6 +659,60 @@ public:
 		return dereferencer ( m_data.begin ( ) + dist );
 	}
 
+	/**
+	 * \brief
+	 * Changes the value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 *
+	 * \param pos the position to set
+	 * \param value the value to place to that position
+	 *
+	 * \return updated iterator to the changed location
+	 */
+	template < class R >
+	reverse_iterator set ( reverse_iterator pos, R && value ) {
+		return set ( const_reverse_iterator ( pos ), std::forward < R > ( value ) );
+	}
+
+	/**
+	 * \brief
+	 * Changes the value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 *
+	 * \param pos the position to set
+	 * \param value the value to place to that position
+	 *
+	 * \return updated iterator to the changed location
+	 */
+	template < class R >
+	reverse_iterator set ( const_reverse_iterator pos, R && value ) {
+		size_type dist = std::distance ( crbegin ( ), pos );
+
+		// If the set value and value at position pos are same instances first clone, then delete
+		delete std::exchange ( m_data.at ( m_data.size ( ) - dist - 1 ), ext::clone ( std::forward < R > ( value ) ) );
+
+		return dereferencer ( m_data.rbegin ( ) + dist );
+	}
+
+	/**
+	 * \brief
+	 * Changes the value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 * \tparam Args ... the types of arguments of the R constructor
+	 *
+	 * \param pos the position to set
+	 * \param args ... the arguments of the R constructor
+	 *
+	 * \return updated iterator to the changed location
+	 */
+	template < class R = T, class ... Args >
+	iterator emplace_set ( iterator pos, Args && ... args ) {
+		return emplace_set ( const_iterator ( pos ), std::forward < Args > ( args ) ... );
+	}
+
 	/**
 	 * \brief
 	 * Changes the value on position given by iterator \p pos
@@ -660,6 +730,56 @@ public:
 		return set ( pos, R ( std::forward < Args > ( args ) ... ) );
 	}
 
+	/**
+	 * \brief
+	 * Changes the value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 * \tparam Args ... the types of arguments of the R constructor
+	 *
+	 * \param pos the position to set
+	 * \param args ... the arguments of the R constructor
+	 *
+	 * \return updated iterator to the changed location
+	 */
+	template < class R = T, class ... Args >
+	reverse_iterator emplace_set ( reverse_iterator pos, Args && ... args ) {
+		return emplace_set ( const_reverse_iterator ( pos ), std::forward < Args > ( args ) ... );
+	}
+
+	/**
+	 * \brief
+	 * Changes the value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 * \tparam Args ... the types of arguments of the R constructor
+	 *
+	 * \param pos the position to set
+	 * \param args ... the arguments of the R constructor
+	 *
+	 * \return updated iterator to the changed location
+	 */
+	template < class R = T, class ... Args >
+	reverse_iterator emplace_set ( const_reverse_iterator pos, Args && ... args ) {
+		return set ( pos, R ( std::forward < Args > ( args ) ... ) );
+	}
+
+	/**
+	 * \brief
+	 * Inserts the value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 *
+	 * \param pos the position to insert at
+	 * \param value the value to insert
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R >
+	iterator insert ( iterator pos, R && value ) {
+		return insert ( const_insert ( pos ), std::forward < R > ( value ) );
+	}
+
 	/**
 	 * \brief
 	 * Inserts the value on position given by iterator \p pos
@@ -676,6 +796,55 @@ public:
 		return dereferencer ( m_data.insert ( pos.base ( ), ext::clone ( std::forward < R > ( value ) ) ) );
 	}
 
+	/**
+	 * \brief
+	 * Inserts the value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 *
+	 * \param pos the position to insert at
+	 * \param value the value to insert
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R >
+	reverse_iterator insert ( reverse_iterator pos, R && value ) {
+		return insert ( const_reverse_iterator ( pos ), std::forward < R > ( value ) );
+	}
+
+	/**
+	 * \brief
+	 * Inserts the value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 *
+	 * \param pos the position to insert at
+	 * \param value the value to insert
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R >
+	reverse_iterator insert ( const_reverse_iterator pos, R && value ) {
+		return dereferencer ( m_data.insert ( pos.base ( ), ext::clone ( std::forward < R > ( value ) ) ) );
+	}
+
+	/**
+	 * \brief
+	 * Inserts the \p count copies of value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 *
+	 * \param pos the position to insert at
+	 * \param count the number of copies to insert
+	 * \param value the value to insert
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R >
+	iterator insert ( iterator pos, size_type count, const R & value ) {
+		return insert ( const_iterator ( pos ), count, value );
+	}
+
 	/**
 	 * \brief
 	 * Inserts the \p count copies of value on position given by iterator \p pos
@@ -697,6 +866,60 @@ public:
 		return res;
 	}
 
+	/**
+	 * \brief
+	 * Inserts the \p count copies of value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 *
+	 * \param pos the position to insert at
+	 * \param count the number of copies to insert
+	 * \param value the value to insert
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R >
+	reverse_iterator insert ( reverse_iterator pos, size_type count, const R & value ) {
+		return insert ( const_reverse_iterator ( pos ), count, value );
+	}
+
+	/**
+	 * \brief
+	 * Inserts the \p count copies of value on position given by iterator \p pos
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 *
+	 * \param pos the position to insert at
+	 * \param count the number of copies to insert
+	 * \param value the value to insert
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R >
+	reverse_iterator insert ( const_reverse_iterator pos, size_type count, const R & value ) {
+		reverse_iterator res = dereferencer ( m_data.insert ( pos, count, NULL ) );
+		for ( size_type i = 0; i < count; ++ i ) {
+			* ( std::next ( res.base ( ) ).base ( ) + i ) = ext::clone ( value );
+		}
+		return res;
+	}
+
+	/**
+	 * \brief
+	 * Inserts the values from the given range to positions starting at given iterator \p pos
+	 *
+	 * \tparam InputIt the iterator type
+	 *
+	 * \param first the begining of the range
+	 * \param last the end of the range
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class InputIt >
+	iterator insert ( iterator pos, InputIt first, InputIt last ) {
+		return insert ( const_iterator ( pos ), first, last );
+	}
+
 	/**
 	 * \brief
 	 * Inserts the values from the given range to positions starting at given iterator \p pos
@@ -719,6 +942,60 @@ public:
 		return res;
 	}
 
+	/**
+	 * \brief
+	 * Inserts the values from the given range to positions starting at given iterator \p pos
+	 *
+	 * \tparam InputIt the iterator type
+	 *
+	 * \param first the begining of the range
+	 * \param last the end of the range
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class InputIt >
+	reverse_iterator insert ( reverse_iterator pos, InputIt first, InputIt last ) {
+		return insert ( const_reverse_iterator ( pos ), first, last );
+	}
+
+	/**
+	 * \brief
+	 * Inserts the values from the given range to positions starting at given iterator \p pos
+	 *
+	 * \tparam InputIt the iterator type
+	 *
+	 * \param first the begining of the range
+	 * \param last the end of the range
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class InputIt >
+	reverse_iterator insert ( const_reverse_iterator pos, InputIt first, InputIt last ) {
+		size_type size = std::distance ( first, last );
+		reverse_iterator res = dereferencer ( m_data.insert ( pos, size, NULL ) );
+
+		for ( size_type i = 0; i < size; ++ first, ++ i )
+			* ( std::next ( res.base ( ) ).base ( ) + i ) = ext::clone ( * first );
+
+		return res;
+	}
+
+	/**
+	 * \brief
+	 * Inserts the values from the given initializer list to positions starting at given iterator \p pos
+	 *
+	 * \tparam R the types stored inside the initializer list
+	 *
+	 * \param pos the position to insert at
+	 * \param ilist the initializer list
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R >
+	iterator insert ( iterator pos, std::initializer_list < R > ilist ) {
+		return insert ( const_iterator ( pos ), std::move ( ilist ) );
+	}
+
 	/**
 	 * \brief
 	 * Inserts the values from the given initializer list to positions starting at given iterator \p pos
@@ -735,6 +1012,55 @@ public:
 		return insert ( pos, ilist.begin ( ), ilist.end ( ) );
 	}
 
+	/**
+	 * \brief
+	 * Inserts the values from the given initializer list to positions starting at given iterator \p pos
+	 *
+	 * \tparam R the types stored inside the initializer list
+	 *
+	 * \param pos the position to insert at
+	 * \param ilist the initializer list
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R >
+	reverse_iterator insert ( reverse_iterator pos, std::initializer_list < R > ilist ) {
+		return insert ( const_reverse_iterator ( pos ), std::move ( ilist ) );
+	}
+
+	/**
+	 * \brief
+	 * Inserts the values from the given initializer list to positions starting at given iterator \p pos
+	 *
+	 * \tparam R the types stored inside the initializer list
+	 *
+	 * \param pos the position to insert at
+	 * \param ilist the initializer list
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R >
+	reverse_iterator insert ( const_reverse_iterator pos, std::initializer_list < R > ilist ) {
+		return insert ( pos, ilist.begin ( ), ilist.end ( ) );
+	}
+
+	/**
+	 * \brief
+	 * Inserts a new value to the container at position given by parameter \p pos. The new value is constructed inside the method from constructor parameters.
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 * \tparam Args ... the types of arguments of the R constructor
+	 *
+	 * \param pos the position to set
+	 * \param args ... the arguments of the R constructor
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R = T, class ... Args >
+	iterator emplace ( iterator pos, Args && ... args ) {
+		return emplace ( const_iterator ( pos ), std::forward < Args > ( args ) ... );
+	}
+
 	/**
 	 * \brief
 	 * Inserts a new value to the container at position given by parameter \p pos. The new value is constructed inside the method from constructor parameters.
@@ -752,6 +1078,52 @@ public:
 		return insert ( pos, R ( std::forward < Args > ( args ) ... ) );
 	}
 
+	/**
+	 * \brief
+	 * Inserts a new value to the container at position given by parameter \p pos. The new value is constructed inside the method from constructor parameters.
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 * \tparam Args ... the types of arguments of the R constructor
+	 *
+	 * \param pos the position to set
+	 * \param args ... the arguments of the R constructor
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R = T, class ... Args >
+	reverse_iterator emplace ( reverse_iterator pos, Args && ... args ) {
+		return emplace ( const_reverse_iterator ( pos ), std::forward < Args > ( args ) ... );
+	}
+
+	/**
+	 * \brief
+	 * Inserts a new value to the container at position given by parameter \p pos. The new value is constructed inside the method from constructor parameters.
+	 *
+	 * \tparam R the actual type of value stored inside the vector
+	 * \tparam Args ... the types of arguments of the R constructor
+	 *
+	 * \param pos the position to set
+	 * \param args ... the arguments of the R constructor
+	 *
+	 * \return updated iterator to the newly inserted value
+	 */
+	template < class R = T, class ... Args >
+	reverse_iterator emplace ( const_reverse_iterator pos, Args && ... args ) {
+		return insert ( pos, R ( std::forward < Args > ( args ) ... ) );
+	}
+
+	/**
+	 * \brief
+	 * Removes element from the container at position given by parameter \p pos
+	 *
+	 * \param pos the iterator pointing to the value to removed
+	 *
+	 * \returns updated iterator to value after the removed one
+	 */
+	iterator erase ( iterator pos ) {
+		return erase ( const_iterator ( pos ) );
+	}
+
 	/**
 	 * \brief
 	 * Removes element from the container at position given by parameter \p pos
@@ -761,10 +1133,48 @@ public:
 	 * \returns updated iterator to value after the removed one
 	 */
 	iterator erase ( const_iterator pos ) {
-		delete * pos.base ( );
+		delete std::addressof ( * pos );
+		return dereferencer ( m_data.erase ( pos.base ( ) ) );
+	}
+
+	/**
+	 * \brief
+	 * Removes element from the container at position given by parameter \p pos
+	 *
+	 * \param pos the iterator pointing to the value to removed
+	 *
+	 * \returns updated iterator to value after the removed one
+	 */
+	reverse_iterator erase ( reverse_iterator pos ) {
+		return erase ( const_reverse_iterator ( pos ) );
+	}
+
+	/**
+	 * \brief
+	 * Removes element from the container at position given by parameter \p pos
+	 *
+	 * \param pos the iterator pointing to the value to removed
+	 *
+	 * \returns updated iterator to value after the removed one
+	 */
+	reverse_iterator erase ( const_reverse_iterator pos ) {
+		delete std::addressof ( * pos );
 		return dereferencer ( m_data.erase ( pos.base ( ) ) );
 	}
 
+	/**
+	 * \brief
+	 * Removes elements from the container in range given parameters \p first and \p last
+	 *
+	 * \param first the begining of the removed range
+	 * \param last the end of the removed range
+	 *
+	 * \returns updated iterator to value after the removed ones
+	 */
+	iterator erase ( iterator first, iterator last ) {
+		return erase ( const_iterator ( first ), const_iterator ( last ) );
+	}
+
 	/**
 	 * \brief
 	 * Removes elements from the container in range given parameters \p first and \p last
@@ -776,7 +1186,36 @@ public:
 	 */
 	iterator erase ( const_iterator first, const_iterator last ) {
 		for ( const_iterator first_copy = first; first_copy != last; ++ first_copy ) {
-			delete * first_copy.base ( );
+			delete std::addressof ( * first_copy );
+		}
+		return dereferencer ( m_data.erase ( first.base ( ), last.base ( ) ) );
+	}
+
+	/**
+	 * \brief
+	 * Removes elements from the container in range given parameters \p first and \p last
+	 *
+	 * \param first the begining of the removed range
+	 * \param last the end of the removed range
+	 *
+	 * \returns updated iterator to value after the removed ones
+	 */
+	reverse_iterator erase ( reverse_iterator first, reverse_iterator last ) {
+		return erase ( const_reverse_iterator ( first ), const_reverse_iterator ( last ) );
+	}
+
+	/**
+	 * \brief
+	 * Removes elements from the container in range given parameters \p first and \p last
+	 *
+	 * \param first the begining of the removed range
+	 * \param last the end of the removed range
+	 *
+	 * \returns updated iterator to value after the removed ones
+	 */
+	reverse_iterator erase ( const_reverse_iterator first, const_reverse_iterator last ) {
+		for ( const_reverse_iterator first_copy = first; first_copy != last; ++ first_copy ) {
+			delete std::addressof ( * first_copy );
 		}
 		return dereferencer ( m_data.erase ( first.base ( ), last.base ( ) ) );
 	}
diff --git a/alib2std/test-src/extensions/container/PtrVectorTest.cpp b/alib2std/test-src/extensions/container/PtrVectorTest.cpp
index 4977595164..448c52e698 100644
--- a/alib2std/test-src/extensions/container/PtrVectorTest.cpp
+++ b/alib2std/test-src/extensions/container/PtrVectorTest.cpp
@@ -117,6 +117,11 @@ TEST_CASE ( "PtrVector", "[unit][std][container]" ) {
 		CHECK ( data [ 1 ] == 2 );
 		CHECK ( data [ 2 ] == 2 );
 		CHECK ( data [ 3 ] == 3 );
+
+		auto iter1 = data.erase ( data.rbegin ( ) );
+		CHECK ( iter1 == data.rbegin ( ) );
+		auto iter2 = data.insert ( data.rbegin ( ), 2 );
+		CHECK ( iter2 == data.rbegin ( ) );
 	}
 
 	SECTION ( "Test Polymorphism" ) {
-- 
GitLab