Ver código fonte

Made convenient List methods for getting indices, so that less code is needed to push something and get the new index.

David Piuva 2 anos atrás
pai
commit
15c65d25f8
1 arquivos alterados com 50 adições e 29 exclusões
  1. 50 29
      Source/DFPSR/collection/List.h

+ 50 - 29
Source/DFPSR/collection/List.h

@@ -40,7 +40,8 @@ namespace dsr {
 //     * Forced use of iterators for cloning and element removal is both overly complex and bloating the code.
 //     * Forced use of iterators for cloning and element removal is both overly complex and bloating the code.
 //       Most people joining your project won't be able to read the code if using std::iterator.
 //       Most people joining your project won't be able to read the code if using std::iterator.
 //       Safer to access elements by index, or an iterating high-level function performing a lambda for each element.
 //       Safer to access elements by index, or an iterating high-level function performing a lambda for each element.
-//       If performance is important, then use Buffer and SafePointer instead, so that you get memory bound and alignment checks for SIMD vectors.
+//       If performance is important, then use Buffer and SafePointer instead,
+//       so that you get memory bound and alignment checks for SIMD vectors.
 //     * Unsigned indices will either force dangerous casting from signed, or prevent
 //     * Unsigned indices will either force dangerous casting from signed, or prevent
 //       the ability to loop backwards without crashing when the x < 0u criteria cannot be met.
 //       the ability to loop backwards without crashing when the x < 0u criteria cannot be met.
 template <typename T>
 template <typename T>
@@ -52,67 +53,72 @@ public:
 	// Constructor
 	// Constructor
 	List() {}
 	List() {}
 	// Clonable by default!
 	// Clonable by default!
-	//   Pass by reference if you don't want to lose your changes and waste time duplicating memory
+	//   Pass by reference if you don't want to lose your changes and waste time duplicating memory.
 	List(const List& source) : backend(std::vector<T>(source.backend.begin(), source.backend.end())) {}
 	List(const List& source) : backend(std::vector<T>(source.backend.begin(), source.backend.end())) {}
-	// Construct using one argument per element
+	// Construct using one argument per element.
 	template<typename... ELEMENTS>
 	template<typename... ELEMENTS>
 	List(ELEMENTS... elements)
 	List(ELEMENTS... elements)
 	: backend({elements...}) {}
 	: backend({elements...}) {}
-	// Post-condition: Returns the number of elements in the array list
+	// Post-condition: Returns the number of elements in the array list.
 	int64_t length() const {
 	int64_t length() const {
 		return (int64_t)this->backend.size();
 		return (int64_t)this->backend.size();
 	}
 	}
-	// Post-condition: Returns the element at index from the range 0..length-1
+	// Post-condition: Returns the element at index from the range 0..length-1.
 	T& operator[] (int64_t index) {
 	T& operator[] (int64_t index) {
 		impl_baseZeroBoundCheck(index, this->length(), "List index");
 		impl_baseZeroBoundCheck(index, this->length(), "List index");
 		return this->backend[index];
 		return this->backend[index];
 	}
 	}
-	// Post-condition: Returns the write-protected element at index from the range 0..length-1
+	// Post-condition: Returns the write-protected element at index from the range 0..length-1.
 	const T& operator[] (int64_t index) const {
 	const T& operator[] (int64_t index) const {
 		impl_baseZeroBoundCheck(index, this->length(), "List index");
 		impl_baseZeroBoundCheck(index, this->length(), "List index");
 		return this->backend[index];
 		return this->backend[index];
 	}
 	}
-	// Post-condition: Returns a reference to the first element
+	// Post-condition: Returns an index to the first element, which is always zero.
+	// Can be used for improving readability when used together with lastIndex.
+	int64_t firstIndex() const { return 0; }
+	// Post-condition: Returns an index to the last element.
+	int64_t lastIndex() const { return this->length() - 1; }
+	// Post-condition: Returns a reference to the first element.
 	T& first() {
 	T& first() {
 		impl_nonZeroLengthCheck(this->length(), "Length");
 		impl_nonZeroLengthCheck(this->length(), "Length");
 		return this->backend[0];
 		return this->backend[0];
 	}
 	}
-	// Post-condition: Returns a reference to the first element from a write protected array list
+	// Post-condition: Returns a reference to the first element from a write protected array list.
 	const T& first() const {
 	const T& first() const {
 		impl_nonZeroLengthCheck(this->length(), "Length");
 		impl_nonZeroLengthCheck(this->length(), "Length");
 		return this->backend[0];
 		return this->backend[0];
 	}
 	}
-	// Post-condition: Returns a reference to the last element
+	// Post-condition: Returns a reference to the last element.
 	T& last() {
 	T& last() {
 		impl_nonZeroLengthCheck(this->length(), "Length");
 		impl_nonZeroLengthCheck(this->length(), "Length");
-		return this->backend[this->length() - 1];
+		return this->backend[this->lastIndex()];
 	}
 	}
-	// Post-condition: Returns a reference to the last element from a write protected array list
+	// Post-condition: Returns a reference to the last element from a write protected array list.
 	const T& last() const {
 	const T& last() const {
 		impl_nonZeroLengthCheck(this->length(), "Length");
 		impl_nonZeroLengthCheck(this->length(), "Length");
-		return this->backend[this->length() - 1];
+		return this->backend[this->lastIndex()];
 	}
 	}
-	// Side-effect: Removes all elements by setting the count to zero
+	// Side-effect: Removes all elements by setting the count to zero.
 	void clear() {
 	void clear() {
 		this->backend.clear();
 		this->backend.clear();
 	}
 	}
-	// Side-effect: Makes sure that the buffer have room for at least minimumLength elements
-	//   Warning! Reallocation may invalidate old pointers and references to elements in the replaced buffer
+	// Side-effect: Makes sure that the buffer have room for at least minimumLength elements.
+	//   Warning! Reallocation may invalidate old pointers and references to elements in the replaced buffer.
 	void reserve(int64_t minimumLength) {
 	void reserve(int64_t minimumLength) {
 		this->backend.reserve(minimumLength);
 		this->backend.reserve(minimumLength);
 	}
 	}
-	// Side-effect: Swap the order of two elements
-	//   Useful for moving and sorting elements
+	// Side-effect: Swap the order of two elements.
+	//   Useful for moving and sorting elements.
 	void swap(int64_t indexA, int64_t indexB) {
 	void swap(int64_t indexA, int64_t indexB) {
 		impl_baseZeroBoundCheck(indexA, this->length(), "Swap index A");
 		impl_baseZeroBoundCheck(indexA, this->length(), "Swap index A");
 		impl_baseZeroBoundCheck(indexB, this->length(), "Swap index B");
 		impl_baseZeroBoundCheck(indexB, this->length(), "Swap index B");
 		std::swap(this->backend[indexA], this->backend[indexB]);
 		std::swap(this->backend[indexA], this->backend[indexB]);
 	}
 	}
-	// Side-effect: Pushes a new element at the end
-	//   Warning! Reallocation may invalidate old pointers and references to elements in the replaced buffer
-	// Post-condition: Returns a reference to the new element in the list
+	// Side-effect: Pushes a new element at the end.
+	//   Warning! Reallocation may invalidate old pointers and references to elements in the replaced buffer.
+	// Post-condition: Returns a reference to the new element in the list.
 	T& push(const T& newValue) {
 	T& push(const T& newValue) {
-		// Optimize for speed by assuming that we have enough memory
+		// Optimize for speed by assuming that we have enough memory.
 		if (this->length() == 0) {
 		if (this->length() == 0) {
 			this->backend.reserve(32);
 			this->backend.reserve(32);
 		} else if (this->length() >= (int64_t)this->backend.capacity()) {
 		} else if (this->length() >= (int64_t)this->backend.capacity()) {
@@ -121,12 +127,19 @@ public:
 		this->backend.push_back(newValue);
 		this->backend.push_back(newValue);
 		return this->last();
 		return this->last();
 	}
 	}
-	// Side-effect: Pushes a new element constructed using the given arguments
-	//   Warning! Reallocation may invalidate old pointers and references to elements in the replaced buffer
-	// Post-condition: Returns a reference to the new element in the list
+	// Side-effect: Pushes a new element at the end.
+	//   Warning! Reallocation may invalidate old pointers and references to elements in the replaced buffer.
+	// Post-condition: Returns an index to the new element in the list.
+	int64_t pushGetIndex(const T& newValue) {
+		this->push(newValue);
+		return this->lastIndex();
+	}
+	// Side-effect: Pushes a new element constructed using the given arguments.
+	//   Warning! Reallocation may invalidate old pointers and references to elements in the replaced buffer.
+	// Post-condition: Returns a reference to the new element in the list.
 	template<typename... ARGS>
 	template<typename... ARGS>
-	T& pushConstruct(ARGS... args) {
-		// Optimize for speed by assuming that we have enough memory
+	T& pushConstruct(ARGS&&... args) {
+		// Optimize for speed by assuming that we have enough memory.
 		if (this->length() == 0) {
 		if (this->length() == 0) {
 			this->backend.reserve(32);
 			this->backend.reserve(32);
 		} else if (this->length() >= (int64_t)this->backend.capacity()) {
 		} else if (this->length() >= (int64_t)this->backend.capacity()) {
@@ -135,12 +148,20 @@ public:
 		this->backend.emplace_back(args...);
 		this->backend.emplace_back(args...);
 		return this->last();
 		return this->last();
 	}
 	}
-	// Side-effect: Deletes the element at removedIndex
-	//   We can assume that the order is stable in the STD implementation, because ListTest.cpp would catch alternative interpretations
+	// Side-effect: Pushes a new element constructed using the given arguments.
+	//   Warning! Reallocation may invalidate old pointers and references to elements in the replaced buffer.
+	// Post-condition: Returns an index to the new element in the list.
+	template<typename... ARGS>
+	int64_t pushConstructGetIndex(ARGS&&... args) {
+		pushConstruct(args...);
+		return this->lastIndex();
+	}
+	// Side-effect: Deletes the element at removedIndex.
+	//   We can assume that the order is stable in the STD implementation, because ListTest.cpp would catch alternative interpretations.
 	void remove(int64_t removedIndex) {
 	void remove(int64_t removedIndex) {
 		this->backend.erase(this->backend.begin() + removedIndex);
 		this->backend.erase(this->backend.begin() + removedIndex);
 	}
 	}
-	// Side-effect: Deletes the last element
+	// Side-effect: Deletes the last element.
 	void pop() {
 	void pop() {
 		this->backend.pop_back();
 		this->backend.pop_back();
 	}
 	}