[Bf-blender-cvs] [9be720d85ef] master: BLI: support accessing nth last element in Array/Span/Vector

Jacques Lucke noreply at git.blender.org
Thu Feb 24 14:50:29 CET 2022


Commit: 9be720d85efb307ad37b73f0f5fffd95629c7e20
Author: Jacques Lucke
Date:   Thu Feb 24 14:45:41 2022 +0100
Branches: master
https://developer.blender.org/rB9be720d85efb307ad37b73f0f5fffd95629c7e20

BLI: support accessing nth last element in Array/Span/Vector

This often helps to make the intend of code more clear compared
to computing the index manually in the caller.

===================================================================

M	source/blender/blenlib/BLI_array.hh
M	source/blender/blenlib/BLI_span.hh
M	source/blender/blenlib/BLI_vector.hh
M	source/blender/blenlib/tests/BLI_array_test.cc
M	source/blender/blenlib/tests/BLI_span_test.cc
M	source/blender/blenlib/tests/BLI_vector_test.cc

===================================================================

diff --git a/source/blender/blenlib/BLI_array.hh b/source/blender/blenlib/BLI_array.hh
index a580f12851e..91dfc81ae27 100644
--- a/source/blender/blenlib/BLI_array.hh
+++ b/source/blender/blenlib/BLI_array.hh
@@ -278,18 +278,20 @@ class Array {
   }
 
   /**
-   * Return a reference to the last element in the array.
-   * This invokes undefined behavior when the array is empty.
+   * Return a reference to the nth last element.
+   * This invokes undefined behavior when the array is too short.
    */
-  const T &last() const
+  const T &last(const int64_t n = 0) const
   {
-    BLI_assert(size_ > 0);
-    return *(data_ + size_ - 1);
+    BLI_assert(n >= 0);
+    BLI_assert(n < size_);
+    return *(data_ + size_ - 1 - n);
   }
-  T &last()
+  T &last(const int64_t n = 0)
   {
-    BLI_assert(size_ > 0);
-    return *(data_ + size_ - 1);
+    BLI_assert(n >= 0);
+    BLI_assert(n < size_);
+    return *(data_ + size_ - 1 - n);
   }
 
   /**
diff --git a/source/blender/blenlib/BLI_span.hh b/source/blender/blenlib/BLI_span.hh
index d82f21a57ff..9ab096094de 100644
--- a/source/blender/blenlib/BLI_span.hh
+++ b/source/blender/blenlib/BLI_span.hh
@@ -307,13 +307,14 @@ template<typename T> class Span {
   }
 
   /**
-   * Returns a reference to the last element in the array. This invokes undefined behavior when the
-   * array is empty.
+   * Returns a reference to the nth last element. This invokes undefined behavior when the span is
+   * too short.
    */
-  constexpr const T &last() const
+  constexpr const T &last(const int64_t n = 0) const
   {
-    BLI_assert(size_ > 0);
-    return data_[size_ - 1];
+    BLI_assert(n >= 0);
+    BLI_assert(n < size_);
+    return data_[size_ - 1 - n];
   }
 
   /**
@@ -673,13 +674,14 @@ template<typename T> class MutableSpan {
   }
 
   /**
-   * Returns a reference to the last element. This invokes undefined behavior when the array is
-   * empty.
+   * Returns a reference to the nth last element. This invokes undefined behavior when the span is
+   * too short.
    */
-  constexpr T &last() const
+  constexpr T &last(const int64_t n = 0) const
   {
-    BLI_assert(size_ > 0);
-    return data_[size_ - 1];
+    BLI_assert(n >= 0);
+    BLI_assert(n < size_);
+    return data_[size_ - 1 - n];
   }
 
   /**
diff --git a/source/blender/blenlib/BLI_vector.hh b/source/blender/blenlib/BLI_vector.hh
index d5d33b8a000..da9ab9c313e 100644
--- a/source/blender/blenlib/BLI_vector.hh
+++ b/source/blender/blenlib/BLI_vector.hh
@@ -639,18 +639,20 @@ class Vector {
   }
 
   /**
-   * Return a reference to the last element in the vector.
-   * This invokes undefined behavior when the vector is empty.
+   * Return a reference to the nth last element.
+   * This invokes undefined behavior when the vector is too short.
    */
-  const T &last() const
+  const T &last(const int64_t n = 0) const
   {
-    BLI_assert(this->size() > 0);
-    return *(end_ - 1);
+    BLI_assert(n >= 0);
+    BLI_assert(n < this->size());
+    return *(end_ - 1 - n);
   }
-  T &last()
+  T &last(const int64_t n = 0)
   {
-    BLI_assert(this->size() > 0);
-    return *(end_ - 1);
+    BLI_assert(n >= 0);
+    BLI_assert(n < this->size());
+    return *(end_ - 1 - n);
   }
 
   /**
diff --git a/source/blender/blenlib/tests/BLI_array_test.cc b/source/blender/blenlib/tests/BLI_array_test.cc
index 6d12b54099a..74eeb5e4e5e 100644
--- a/source/blender/blenlib/tests/BLI_array_test.cc
+++ b/source/blender/blenlib/tests/BLI_array_test.cc
@@ -231,9 +231,11 @@ TEST(array, Last)
 {
   Array<int> array = {5, 7, 8, 9};
   EXPECT_EQ(array.last(), 9);
+  EXPECT_EQ(array.last(1), 8);
   array.last() = 1;
   EXPECT_EQ(array[3], 1);
   EXPECT_EQ(const_cast<const Array<int> &>(array).last(), 1);
+  EXPECT_EQ(const_cast<const Array<int> &>(array).last(2), 7);
 }
 
 TEST(array, Reinitialize)
diff --git a/source/blender/blenlib/tests/BLI_span_test.cc b/source/blender/blenlib/tests/BLI_span_test.cc
index 35fb22b3257..0bd34250deb 100644
--- a/source/blender/blenlib/tests/BLI_span_test.cc
+++ b/source/blender/blenlib/tests/BLI_span_test.cc
@@ -247,6 +247,8 @@ TEST(span, FirstLast)
   Span<int> a_span(a);
   EXPECT_EQ(a_span.first(), 6);
   EXPECT_EQ(a_span.last(), 9);
+  EXPECT_EQ(a_span.last(1), 8);
+  EXPECT_EQ(a_span.last(2), 7);
 }
 
 TEST(span, FirstLast_OneElement)
@@ -255,6 +257,7 @@ TEST(span, FirstLast_OneElement)
   Span<int> a_span(&a, 1);
   EXPECT_EQ(a_span.first(), 3);
   EXPECT_EQ(a_span.last(), 3);
+  EXPECT_EQ(a_span.last(0), 3);
 }
 
 TEST(span, Get)
diff --git a/source/blender/blenlib/tests/BLI_vector_test.cc b/source/blender/blenlib/tests/BLI_vector_test.cc
index 40cda20c395..29b6d2b41fe 100644
--- a/source/blender/blenlib/tests/BLI_vector_test.cc
+++ b/source/blender/blenlib/tests/BLI_vector_test.cc
@@ -447,6 +447,9 @@ TEST(vector, Last)
 {
   Vector<int> a{3, 5, 7};
   EXPECT_EQ(a.last(), 7);
+  EXPECT_EQ(a.last(0), 7);
+  EXPECT_EQ(a.last(1), 5);
+  EXPECT_EQ(a.last(2), 3);
 }
 
 TEST(vector, AppendNTimes)



More information about the Bf-blender-cvs mailing list