From 97e76ae05575a77bf71015e0b064d082d16c884c Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 13 Mar 2019 09:03:54 +0100
Subject: [PATCH] allow reverse iterators in vector::insert, erase, emplace,
 ...

---
 alib2std/src/extensions/container/vector.hpp  | 210 ++++++++++++++++++
 .../extensions/container/VectorTest.cpp       |  17 ++
 2 files changed, 227 insertions(+)

diff --git a/alib2std/src/extensions/container/vector.hpp b/alib2std/src/extensions/container/vector.hpp
index cacfd39af1..2b768e9221 100644
--- a/alib2std/src/extensions/container/vector.hpp
+++ b/alib2std/src/extensions/container/vector.hpp
@@ -57,6 +57,31 @@ public:
 	 * Inherit operator = of the standard vector
 	 */
 	using std::vector< T, Alloc >::operator =;
+
+	/**
+	 * \brief
+	 * The type of values iterator.
+	 */
+	using iterator = typename std::vector < T, Alloc >::iterator;
+
+	/**
+	 * \brief
+	 * The type of constant values iterator.
+	 */
+	using const_iterator = typename std::vector < T, Alloc >::const_iterator;
+
+	/**
+	 * \brief
+	 * The type of reverse values iterator.
+	 */
+	using reverse_iterator = typename std::vector < T, Alloc >::reverse_iterator;
+
+	/**
+	 * \brief
+	 * The type of constant reverse values iterator.
+	 */
+	using const_reverse_iterator = typename std::vector < T, Alloc >::const_reverse_iterator;
+
 #ifndef __clang__
 
 	/**
@@ -190,6 +215,191 @@ public:
 		auto beginIter = std::move ( * this ).begin ( );
 		return ext::iterator_range < decltype ( endIter ) > ( beginIter, endIter );
 	}
+
+	/**
+	 * Get original insert on the top level.
+	 */
+	using std::vector < T, Alloc >::insert;
+
+	/**
+	 * \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
+	 */
+	reverse_iterator insert ( const_reverse_iterator pos, const T & value ) {
+		return reverse_iterator ( std::next ( insert ( pos.base ( ), 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
+	 */
+	reverse_iterator insert ( const_reverse_iterator pos, T && value ) {
+		return reverse_iterator ( std::next ( insert ( pos.base ( ), std::move ( 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
+	 */
+	reverse_iterator insert ( const_reverse_iterator pos, size_t count, const T & value ) {
+		return reverse_iterator ( std::next ( insert ( pos.base ( ), count, value ) ) );
+	}
+
+	/**
+	 * \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 ) {
+		return reverse_iterator ( std::next ( insert ( pos.base ( ), first, last ) ) );
+	}
+
+	/**
+	 * \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
+	 */
+	reverse_iterator insert ( const_reverse_iterator pos, std::initializer_list < T > ilist ) {
+		return reverse_iterator ( std::next ( insert ( pos.base ( ), std::move ( ilist ) ) ) );
+	}
+
+	/**
+	 * Get original emplace on the top level.
+	 */
+	using std::vector < T, Alloc >::emplace;
+
+	/**
+	 * \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 reverse_iterator ( std::next ( emplace ( pos.base ( ), std::forward < Args > ( args ) ... ) ) );
+	}
+
+	/**
+	 * Get original emplace on the top level.
+	 */
+	using std::vector < T, Alloc >::erase;
+
+	/**
+	 * \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
+	 *
+	 * \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 ) {
+		return reverse_iterator ( erase ( std::next ( 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
+	 *
+	 * \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 ) {
+		return reverse_iterator ( erase ( std::next ( first ).base ( ), std::next ( last ).base ( ) ) );
+	}
+
 };
 
 /**
diff --git a/alib2std/test-src/extensions/container/VectorTest.cpp b/alib2std/test-src/extensions/container/VectorTest.cpp
index 4bfe6c3ac7..4155ca2b74 100644
--- a/alib2std/test-src/extensions/container/VectorTest.cpp
+++ b/alib2std/test-src/extensions/container/VectorTest.cpp
@@ -41,11 +41,28 @@ namespace {
 TEST_CASE ( "Vector", "[unit][std][container]" ) {
 	SECTION ( "Properties test" ) {
 		ext::vector<int> data = {1, 2, 3, 4};
+		ext::vector<int> dataRef = {1, 2, 3, 4};
 
 		const ext::vector<int>& constData = data;
 
+		auto iter1 = data.erase ( data.begin ( ) );
+		CHECK ( iter1 == data.begin ( ) );
+		auto iter2 = data.erase ( data.rbegin ( ) );
+		CHECK ( iter2 == data.rbegin ( ) );
+
+		CHECK ( data.size ( ) == 2 );
+
+		auto iter3 = data.insert ( data.begin ( ), 1 );
+		CHECK ( iter3 == data.begin ( ) );
+		auto iter4 = data.insert ( data.rbegin ( ), 4 );
+		CHECK ( iter4 == data.rbegin ( ) );
+
+		CHECK ( data.size ( ) == 4 );
+
 		CHECK((std::is_same<decltype(constData[0]), const int&>::value));
 
+		CHECK ( data == dataRef );
+
 		int moves;
 		int copies;
 
-- 
GitLab