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.
This commit is contained in:
Jacques Lucke 2022-02-24 14:45:41 +01:00
parent 7cab7eb3d6
commit 9be720d85e
6 changed files with 40 additions and 26 deletions

View File

@ -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);
}
/**

View File

@ -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];
}
/**

View File

@ -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);
}
/**

View File

@ -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)

View File

@ -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)

View File

@ -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)