BLI: constexpr Span, IndexRange, StringRef(Null/Base)
Motivated by `std::string_view` being usable in const (compile-time) context. One functional change was needed for StringRef: `std::char_traits<char>::length(str)` instead of `strlen`. Reviewed By: JacquesLucke, LazyDodo Differential Revision: https://developer.blender.org/D9788
This commit is contained in:
parent
e671c548e6
commit
d23a5b1d88
|
@ -73,21 +73,22 @@ class IndexRange {
|
|||
int64_t size_ = 0;
|
||||
|
||||
public:
|
||||
IndexRange() = default;
|
||||
constexpr IndexRange() = default;
|
||||
|
||||
explicit IndexRange(int64_t size) : start_(0), size_(size)
|
||||
constexpr explicit IndexRange(int64_t size) : start_(0), size_(size)
|
||||
{
|
||||
BLI_assert(size >= 0);
|
||||
}
|
||||
|
||||
IndexRange(int64_t start, int64_t size) : start_(start), size_(size)
|
||||
constexpr IndexRange(int64_t start, int64_t size) : start_(start), size_(size)
|
||||
{
|
||||
BLI_assert(start >= 0);
|
||||
BLI_assert(size >= 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
IndexRange(const tbb::blocked_range<T> &range) : start_(range.begin()), size_(range.size())
|
||||
constexpr IndexRange(const tbb::blocked_range<T> &range)
|
||||
: start_(range.begin()), size_(range.size())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -96,33 +97,33 @@ class IndexRange {
|
|||
int64_t current_;
|
||||
|
||||
public:
|
||||
Iterator(int64_t current) : current_(current)
|
||||
constexpr Iterator(int64_t current) : current_(current)
|
||||
{
|
||||
}
|
||||
|
||||
Iterator &operator++()
|
||||
constexpr Iterator &operator++()
|
||||
{
|
||||
current_++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator &iterator) const
|
||||
constexpr bool operator!=(const Iterator &iterator) const
|
||||
{
|
||||
return current_ != iterator.current_;
|
||||
}
|
||||
|
||||
int64_t operator*() const
|
||||
constexpr int64_t operator*() const
|
||||
{
|
||||
return current_;
|
||||
}
|
||||
};
|
||||
|
||||
Iterator begin() const
|
||||
constexpr Iterator begin() const
|
||||
{
|
||||
return Iterator(start_);
|
||||
}
|
||||
|
||||
Iterator end() const
|
||||
constexpr Iterator end() const
|
||||
{
|
||||
return Iterator(start_ + size_);
|
||||
}
|
||||
|
@ -130,7 +131,7 @@ class IndexRange {
|
|||
/**
|
||||
* Access an element in the range.
|
||||
*/
|
||||
int64_t operator[](int64_t index) const
|
||||
constexpr int64_t operator[](int64_t index) const
|
||||
{
|
||||
BLI_assert(index >= 0);
|
||||
BLI_assert(index < this->size());
|
||||
|
@ -140,7 +141,7 @@ class IndexRange {
|
|||
/**
|
||||
* Two ranges compare equal when they contain the same numbers.
|
||||
*/
|
||||
friend bool operator==(IndexRange a, IndexRange b)
|
||||
constexpr friend bool operator==(IndexRange a, IndexRange b)
|
||||
{
|
||||
return (a.size_ == b.size_) && (a.start_ == b.start_ || a.size_ == 0);
|
||||
}
|
||||
|
@ -148,7 +149,7 @@ class IndexRange {
|
|||
/**
|
||||
* Get the amount of numbers in the range.
|
||||
*/
|
||||
int64_t size() const
|
||||
constexpr int64_t size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
@ -156,7 +157,7 @@ class IndexRange {
|
|||
/**
|
||||
* Create a new range starting at the end of the current one.
|
||||
*/
|
||||
IndexRange after(int64_t n) const
|
||||
constexpr IndexRange after(int64_t n) const
|
||||
{
|
||||
BLI_assert(n >= 0);
|
||||
return IndexRange(start_ + size_, n);
|
||||
|
@ -165,7 +166,7 @@ class IndexRange {
|
|||
/**
|
||||
* Create a new range that ends at the start of the current one.
|
||||
*/
|
||||
IndexRange before(int64_t n) const
|
||||
constexpr IndexRange before(int64_t n) const
|
||||
{
|
||||
BLI_assert(n >= 0);
|
||||
return IndexRange(start_ - n, n);
|
||||
|
@ -175,7 +176,7 @@ class IndexRange {
|
|||
* Get the first element in the range.
|
||||
* Asserts when the range is empty.
|
||||
*/
|
||||
int64_t first() const
|
||||
constexpr int64_t first() const
|
||||
{
|
||||
BLI_assert(this->size() > 0);
|
||||
return start_;
|
||||
|
@ -185,7 +186,7 @@ class IndexRange {
|
|||
* Get the last element in the range.
|
||||
* Asserts when the range is empty.
|
||||
*/
|
||||
int64_t last() const
|
||||
constexpr int64_t last() const
|
||||
{
|
||||
BLI_assert(this->size() > 0);
|
||||
return start_ + size_ - 1;
|
||||
|
@ -194,7 +195,7 @@ class IndexRange {
|
|||
/**
|
||||
* Get the element one after the end. The returned value is undefined when the range is empty.
|
||||
*/
|
||||
int64_t one_after_last() const
|
||||
constexpr int64_t one_after_last() const
|
||||
{
|
||||
return start_ + size_;
|
||||
}
|
||||
|
@ -202,7 +203,7 @@ class IndexRange {
|
|||
/**
|
||||
* Get the first element in the range. The returned value is undefined when the range is empty.
|
||||
*/
|
||||
int64_t start() const
|
||||
constexpr int64_t start() const
|
||||
{
|
||||
return start_;
|
||||
}
|
||||
|
@ -210,7 +211,7 @@ class IndexRange {
|
|||
/**
|
||||
* Returns true when the range contains a certain number, otherwise false.
|
||||
*/
|
||||
bool contains(int64_t value) const
|
||||
constexpr bool contains(int64_t value) const
|
||||
{
|
||||
return value >= start_ && value < start_ + size_;
|
||||
}
|
||||
|
@ -218,7 +219,7 @@ class IndexRange {
|
|||
/**
|
||||
* Returns a new range, that contains a sub-interval of the current one.
|
||||
*/
|
||||
IndexRange slice(int64_t start, int64_t size) const
|
||||
constexpr IndexRange slice(int64_t start, int64_t size) const
|
||||
{
|
||||
BLI_assert(start >= 0);
|
||||
BLI_assert(size >= 0);
|
||||
|
@ -226,7 +227,7 @@ class IndexRange {
|
|||
BLI_assert(new_start + size <= start_ + size_ || size == 0);
|
||||
return IndexRange(new_start, size);
|
||||
}
|
||||
IndexRange slice(IndexRange range) const
|
||||
constexpr IndexRange slice(IndexRange range) const
|
||||
{
|
||||
return this->slice(range.start(), range.size());
|
||||
}
|
||||
|
|
|
@ -93,15 +93,15 @@ template<typename T> class Span {
|
|||
/**
|
||||
* Create a reference to an empty array.
|
||||
*/
|
||||
Span() = default;
|
||||
constexpr Span() = default;
|
||||
|
||||
Span(const T *start, int64_t size) : data_(start), size_(size)
|
||||
constexpr Span(const T *start, int64_t size) : data_(start), size_(size)
|
||||
{
|
||||
BLI_assert(size >= 0);
|
||||
}
|
||||
|
||||
template<typename U, typename std::enable_if_t<is_convertible_pointer_v<U, T>> * = nullptr>
|
||||
Span(const U *start, int64_t size) : data_(static_cast<const T *>(start)), size_(size)
|
||||
constexpr Span(const U *start, int64_t size) : data_(static_cast<const T *>(start)), size_(size)
|
||||
{
|
||||
BLI_assert(size >= 0);
|
||||
}
|
||||
|
@ -117,16 +117,17 @@ template<typename T> class Span {
|
|||
* Span<int> span = {1, 2, 3, 4};
|
||||
* call_function_with_array(span);
|
||||
*/
|
||||
Span(const std::initializer_list<T> &list)
|
||||
constexpr Span(const std::initializer_list<T> &list)
|
||||
: Span(list.begin(), static_cast<int64_t>(list.size()))
|
||||
{
|
||||
}
|
||||
|
||||
Span(const std::vector<T> &vector) : Span(vector.data(), static_cast<int64_t>(vector.size()))
|
||||
constexpr Span(const std::vector<T> &vector)
|
||||
: Span(vector.data(), static_cast<int64_t>(vector.size()))
|
||||
{
|
||||
}
|
||||
|
||||
template<std::size_t N> Span(const std::array<T, N> &array) : Span(array.data(), N)
|
||||
template<std::size_t N> constexpr Span(const std::array<T, N> &array) : Span(array.data(), N)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -135,7 +136,7 @@ template<typename T> class Span {
|
|||
* Span<T *> -> Span<const T *>
|
||||
*/
|
||||
template<typename U, typename std::enable_if_t<is_convertible_pointer_v<U, T>> * = nullptr>
|
||||
Span(Span<U> array) : data_(static_cast<const T *>(array.data())), size_(array.size())
|
||||
constexpr Span(Span<U> array) : data_(static_cast<const T *>(array.data())), size_(array.size())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -143,7 +144,7 @@ template<typename T> class Span {
|
|||
* Returns a contiguous part of the array. This invokes undefined behavior when the slice does
|
||||
* not stay within the bounds of the array.
|
||||
*/
|
||||
Span slice(int64_t start, int64_t size) const
|
||||
constexpr Span slice(int64_t start, int64_t size) const
|
||||
{
|
||||
BLI_assert(start >= 0);
|
||||
BLI_assert(size >= 0);
|
||||
|
@ -151,7 +152,7 @@ template<typename T> class Span {
|
|||
return Span(data_ + start, size);
|
||||
}
|
||||
|
||||
Span slice(IndexRange range) const
|
||||
constexpr Span slice(IndexRange range) const
|
||||
{
|
||||
return this->slice(range.start(), range.size());
|
||||
}
|
||||
|
@ -160,7 +161,7 @@ template<typename T> class Span {
|
|||
* Returns a new Span with n elements removed from the beginning. This invokes undefined
|
||||
* behavior when the array is too small.
|
||||
*/
|
||||
Span drop_front(int64_t n) const
|
||||
constexpr Span drop_front(int64_t n) const
|
||||
{
|
||||
BLI_assert(n >= 0);
|
||||
BLI_assert(n <= this->size());
|
||||
|
@ -171,7 +172,7 @@ template<typename T> class Span {
|
|||
* Returns a new Span with n elements removed from the beginning. This invokes undefined
|
||||
* behavior when the array is too small.
|
||||
*/
|
||||
Span drop_back(int64_t n) const
|
||||
constexpr Span drop_back(int64_t n) const
|
||||
{
|
||||
BLI_assert(n >= 0);
|
||||
BLI_assert(n <= this->size());
|
||||
|
@ -182,7 +183,7 @@ template<typename T> class Span {
|
|||
* Returns a new Span that only contains the first n elements. This invokes undefined
|
||||
* behavior when the array is too small.
|
||||
*/
|
||||
Span take_front(int64_t n) const
|
||||
constexpr Span take_front(int64_t n) const
|
||||
{
|
||||
BLI_assert(n >= 0);
|
||||
BLI_assert(n <= this->size());
|
||||
|
@ -193,7 +194,7 @@ template<typename T> class Span {
|
|||
* Returns a new Span that only contains the last n elements. This invokes undefined
|
||||
* behavior when the array is too small.
|
||||
*/
|
||||
Span take_back(int64_t n) const
|
||||
constexpr Span take_back(int64_t n) const
|
||||
{
|
||||
BLI_assert(n >= 0);
|
||||
BLI_assert(n <= this->size());
|
||||
|
@ -204,25 +205,25 @@ template<typename T> class Span {
|
|||
* Returns the pointer to the beginning of the referenced array. This may be nullptr when the
|
||||
* size is zero.
|
||||
*/
|
||||
const T *data() const
|
||||
constexpr const T *data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
const T *begin() const
|
||||
constexpr const T *begin() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
const T *end() const
|
||||
constexpr const T *end() const
|
||||
{
|
||||
return data_ + size_;
|
||||
}
|
||||
|
||||
std::reverse_iterator<const T *> rbegin() const
|
||||
constexpr std::reverse_iterator<const T *> rbegin() const
|
||||
{
|
||||
return std::reverse_iterator<const T *>(this->end());
|
||||
}
|
||||
std::reverse_iterator<const T *> rend() const
|
||||
constexpr std::reverse_iterator<const T *> rend() const
|
||||
{
|
||||
return std::reverse_iterator<const T *>(this->begin());
|
||||
}
|
||||
|
@ -231,7 +232,7 @@ template<typename T> class Span {
|
|||
* Access an element in the array. This invokes undefined behavior when the index is out of
|
||||
* bounds.
|
||||
*/
|
||||
const T &operator[](int64_t index) const
|
||||
constexpr const T &operator[](int64_t index) const
|
||||
{
|
||||
BLI_assert(index >= 0);
|
||||
BLI_assert(index < size_);
|
||||
|
@ -241,7 +242,7 @@ template<typename T> class Span {
|
|||
/**
|
||||
* Returns the number of elements in the referenced array.
|
||||
*/
|
||||
int64_t size() const
|
||||
constexpr int64_t size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
@ -249,7 +250,7 @@ template<typename T> class Span {
|
|||
/**
|
||||
* Returns true if the size is zero.
|
||||
*/
|
||||
bool is_empty() const
|
||||
constexpr bool is_empty() const
|
||||
{
|
||||
return size_ == 0;
|
||||
}
|
||||
|
@ -257,7 +258,7 @@ template<typename T> class Span {
|
|||
/**
|
||||
* Returns the number of bytes referenced by this Span.
|
||||
*/
|
||||
int64_t size_in_bytes() const
|
||||
constexpr int64_t size_in_bytes() const
|
||||
{
|
||||
return sizeof(T) * size_;
|
||||
}
|
||||
|
@ -266,7 +267,7 @@ template<typename T> class Span {
|
|||
* Does a linear search to see of the value is in the array.
|
||||
* Returns true if it is, otherwise false.
|
||||
*/
|
||||
bool contains(const T &value) const
|
||||
constexpr bool contains(const T &value) const
|
||||
{
|
||||
for (const T &element : *this) {
|
||||
if (element == value) {
|
||||
|
@ -280,7 +281,7 @@ template<typename T> class Span {
|
|||
* Does a constant time check to see if the pointer points to a value in the referenced array.
|
||||
* Return true if it is, otherwise false.
|
||||
*/
|
||||
bool contains_ptr(const T *ptr) const
|
||||
constexpr bool contains_ptr(const T *ptr) const
|
||||
{
|
||||
return (this->begin() <= ptr) && (ptr < this->end());
|
||||
}
|
||||
|
@ -289,7 +290,7 @@ template<typename T> class Span {
|
|||
* Does a linear search to count how often the value is in the array.
|
||||
* Returns the number of occurrences.
|
||||
*/
|
||||
int64_t count(const T &value) const
|
||||
constexpr int64_t count(const T &value) const
|
||||
{
|
||||
int64_t counter = 0;
|
||||
for (const T &element : *this) {
|
||||
|
@ -304,7 +305,7 @@ template<typename T> class Span {
|
|||
* Return a reference to the first element in the array. This invokes undefined behavior when the
|
||||
* array is empty.
|
||||
*/
|
||||
const T &first() const
|
||||
constexpr const T &first() const
|
||||
{
|
||||
BLI_assert(size_ > 0);
|
||||
return data_[0];
|
||||
|
@ -314,7 +315,7 @@ template<typename T> class Span {
|
|||
* Returns a reference to the last element in the array. This invokes undefined behavior when the
|
||||
* array is empty.
|
||||
*/
|
||||
const T &last() const
|
||||
constexpr const T &last() const
|
||||
{
|
||||
BLI_assert(size_ > 0);
|
||||
return data_[size_ - 1];
|
||||
|
@ -324,7 +325,7 @@ template<typename T> class Span {
|
|||
* Returns the element at the given index. If the index is out of range, return the fallback
|
||||
* value.
|
||||
*/
|
||||
T get(int64_t index, const T &fallback) const
|
||||
constexpr T get(int64_t index, const T &fallback) const
|
||||
{
|
||||
if (index < size_ && index >= 0) {
|
||||
return data_[index];
|
||||
|
@ -336,7 +337,7 @@ template<typename T> class Span {
|
|||
* Check if the array contains duplicates. Does a linear search for every element. So the total
|
||||
* running time is O(n^2). Only use this for small arrays.
|
||||
*/
|
||||
bool has_duplicates__linear_search() const
|
||||
constexpr bool has_duplicates__linear_search() const
|
||||
{
|
||||
/* The size should really be smaller than that. If it is not, the calling code should be
|
||||
* changed. */
|
||||
|
@ -358,7 +359,7 @@ template<typename T> class Span {
|
|||
* called on small arrays, because it has a running time of O(n*m) where n and m are the sizes of
|
||||
* the arrays.
|
||||
*/
|
||||
bool intersects__linear_search(Span other) const
|
||||
constexpr bool intersects__linear_search(Span other) const
|
||||
{
|
||||
/* The size should really be smaller than that. If it is not, the calling code should be
|
||||
* changed. */
|
||||
|
@ -377,7 +378,7 @@ template<typename T> class Span {
|
|||
* Returns the index of the first occurrence of the given value. This invokes undefined behavior
|
||||
* when the value is not in the array.
|
||||
*/
|
||||
int64_t first_index(const T &search_value) const
|
||||
constexpr int64_t first_index(const T &search_value) const
|
||||
{
|
||||
const int64_t index = this->first_index_try(search_value);
|
||||
BLI_assert(index >= 0);
|
||||
|
@ -387,7 +388,7 @@ template<typename T> class Span {
|
|||
/**
|
||||
* Returns the index of the first occurrence of the given value or -1 if it does not exist.
|
||||
*/
|
||||
int64_t first_index_try(const T &search_value) const
|
||||
constexpr int64_t first_index_try(const T &search_value) const
|
||||
{
|
||||
for (int64_t i = 0; i < size_; i++) {
|
||||
if (data_[i] == search_value) {
|
||||
|
@ -401,7 +402,7 @@ template<typename T> class Span {
|
|||
* Utility to make it more convenient to iterate over all indices that can be used with this
|
||||
* array.
|
||||
*/
|
||||
IndexRange index_range() const
|
||||
constexpr IndexRange index_range() const
|
||||
{
|
||||
return IndexRange(size_);
|
||||
}
|
||||
|
@ -409,7 +410,7 @@ template<typename T> class Span {
|
|||
/**
|
||||
* Returns a new Span to the same underlying memory buffer. No conversions are done.
|
||||
*/
|
||||
template<typename NewT> Span<NewT> cast() const
|
||||
template<typename NewT> Span<NewT> constexpr cast() const
|
||||
{
|
||||
BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0);
|
||||
int64_t new_size = size_ * sizeof(T) / sizeof(NewT);
|
||||
|
@ -450,21 +451,22 @@ template<typename T> class MutableSpan {
|
|||
int64_t size_;
|
||||
|
||||
public:
|
||||
MutableSpan() = default;
|
||||
constexpr MutableSpan() = default;
|
||||
|
||||
MutableSpan(T *start, const int64_t size) : data_(start), size_(size)
|
||||
constexpr MutableSpan(T *start, const int64_t size) : data_(start), size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
MutableSpan(std::vector<T> &vector) : MutableSpan(vector.data(), vector.size())
|
||||
constexpr MutableSpan(std::vector<T> &vector) : MutableSpan(vector.data(), vector.size())
|
||||
{
|
||||
}
|
||||
|
||||
template<std::size_t N> MutableSpan(std::array<T, N> &array) : MutableSpan(array.data(), N)
|
||||
template<std::size_t N>
|
||||
constexpr MutableSpan(std::array<T, N> &array) : MutableSpan(array.data(), N)
|
||||
{
|
||||
}
|
||||
|
||||
operator Span<T>() const
|
||||
constexpr operator Span<T>() const
|
||||
{
|
||||
return Span<T>(data_, size_);
|
||||
}
|
||||
|
@ -472,7 +474,7 @@ template<typename T> class MutableSpan {
|
|||
/**
|
||||
* Returns the number of elements in the array.
|
||||
*/
|
||||
int64_t size() const
|
||||
constexpr int64_t size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
@ -480,7 +482,7 @@ template<typename T> class MutableSpan {
|
|||
/**
|
||||
* Replace all elements in the referenced array with the given value.
|
||||
*/
|
||||
void fill(const T &value)
|
||||
constexpr void fill(const T &value)
|
||||
{
|
||||
initialized_fill_n(data_, size_, value);
|
||||
}
|
||||
|
@ -489,7 +491,7 @@ template<typename T> class MutableSpan {
|
|||
* Replace a subset of all elements with the given value. This invokes undefined behavior when
|
||||
* one of the indices is out of bounds.
|
||||
*/
|
||||
void fill_indices(Span<int64_t> indices, const T &value)
|
||||
constexpr void fill_indices(Span<int64_t> indices, const T &value)
|
||||
{
|
||||
for (int64_t i : indices) {
|
||||
BLI_assert(i < size_);
|
||||
|
@ -501,30 +503,30 @@ template<typename T> class MutableSpan {
|
|||
* Returns a pointer to the beginning of the referenced array. This may be nullptr, when the size
|
||||
* is zero.
|
||||
*/
|
||||
T *data() const
|
||||
constexpr T *data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
T *begin() const
|
||||
constexpr T *begin() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
T *end() const
|
||||
constexpr T *end() const
|
||||
{
|
||||
return data_ + size_;
|
||||
}
|
||||
|
||||
std::reverse_iterator<T *> rbegin() const
|
||||
constexpr std::reverse_iterator<T *> rbegin() const
|
||||
{
|
||||
return std::reverse_iterator<T *>(this->end());
|
||||
}
|
||||
std::reverse_iterator<T *> rend() const
|
||||
constexpr std::reverse_iterator<T *> rend() const
|
||||
{
|
||||
return std::reverse_iterator<T *>(this->begin());
|
||||
}
|
||||
|
||||
T &operator[](const int64_t index) const
|
||||
constexpr T &operator[](const int64_t index) const
|
||||
{
|
||||
BLI_assert(index < this->size());
|
||||
return data_[index];
|
||||
|
@ -534,7 +536,7 @@ template<typename T> class MutableSpan {
|
|||
* Returns a contiguous part of the array. This invokes undefined behavior when the slice would
|
||||
* go out of bounds.
|
||||
*/
|
||||
MutableSpan slice(const int64_t start, const int64_t length) const
|
||||
constexpr MutableSpan slice(const int64_t start, const int64_t length) const
|
||||
{
|
||||
BLI_assert(start + length <= this->size());
|
||||
return MutableSpan(data_ + start, length);
|
||||
|
@ -544,7 +546,7 @@ template<typename T> class MutableSpan {
|
|||
* Returns a new MutableSpan with n elements removed from the beginning. This invokes
|
||||
* undefined behavior when the array is too small.
|
||||
*/
|
||||
MutableSpan drop_front(const int64_t n) const
|
||||
constexpr MutableSpan drop_front(const int64_t n) const
|
||||
{
|
||||
BLI_assert(n <= this->size());
|
||||
return this->slice(n, this->size() - n);
|
||||
|
@ -554,7 +556,7 @@ template<typename T> class MutableSpan {
|
|||
* Returns a new MutableSpan with n elements removed from the end. This invokes undefined
|
||||
* behavior when the array is too small.
|
||||
*/
|
||||
MutableSpan drop_back(const int64_t n) const
|
||||
constexpr MutableSpan drop_back(const int64_t n) const
|
||||
{
|
||||
BLI_assert(n <= this->size());
|
||||
return this->slice(0, this->size() - n);
|
||||
|
@ -564,7 +566,7 @@ template<typename T> class MutableSpan {
|
|||
* Returns a new MutableSpan that only contains the first n elements. This invokes undefined
|
||||
* behavior when the array is too small.
|
||||
*/
|
||||
MutableSpan take_front(const int64_t n) const
|
||||
constexpr MutableSpan take_front(const int64_t n) const
|
||||
{
|
||||
BLI_assert(n <= this->size());
|
||||
return this->slice(0, n);
|
||||
|
@ -574,7 +576,7 @@ template<typename T> class MutableSpan {
|
|||
* Return a new MutableSpan that only contains the last n elements. This invokes undefined
|
||||
* behavior when the array is too small.
|
||||
*/
|
||||
MutableSpan take_back(const int64_t n) const
|
||||
constexpr MutableSpan take_back(const int64_t n) const
|
||||
{
|
||||
BLI_assert(n <= this->size());
|
||||
return this->slice(this->size() - n, n);
|
||||
|
@ -584,7 +586,7 @@ template<typename T> class MutableSpan {
|
|||
* Returns an (immutable) Span that references the same array. This is usually not needed,
|
||||
* due to implicit conversions. However, sometimes automatic type deduction needs some help.
|
||||
*/
|
||||
Span<T> as_span() const
|
||||
constexpr Span<T> as_span() const
|
||||
{
|
||||
return Span<T>(data_, size_);
|
||||
}
|
||||
|
@ -593,7 +595,7 @@ template<typename T> class MutableSpan {
|
|||
* Utility to make it more convenient to iterate over all indices that can be used with this
|
||||
* array.
|
||||
*/
|
||||
IndexRange index_range() const
|
||||
constexpr IndexRange index_range() const
|
||||
{
|
||||
return IndexRange(size_);
|
||||
}
|
||||
|
@ -602,7 +604,7 @@ template<typename T> class MutableSpan {
|
|||
* Returns a reference to the last element. This invokes undefined behavior when the array is
|
||||
* empty.
|
||||
*/
|
||||
T &last() const
|
||||
constexpr T &last() const
|
||||
{
|
||||
BLI_assert(size_ > 0);
|
||||
return data_[size_ - 1];
|
||||
|
@ -612,7 +614,7 @@ template<typename T> class MutableSpan {
|
|||
* Does a linear search to count how often the value is in the array.
|
||||
* Returns the number of occurrences.
|
||||
*/
|
||||
int64_t count(const T &value) const
|
||||
constexpr int64_t count(const T &value) const
|
||||
{
|
||||
int64_t counter = 0;
|
||||
for (const T &element : *this) {
|
||||
|
@ -628,7 +630,7 @@ template<typename T> class MutableSpan {
|
|||
* destination contains uninitialized data and T is not trivially copy constructible.
|
||||
* The size of both spans is expected to be the same.
|
||||
*/
|
||||
void copy_from(Span<T> values)
|
||||
constexpr void copy_from(Span<T> values)
|
||||
{
|
||||
BLI_assert(size_ == values.size());
|
||||
initialized_copy_n(values.data(), size_, data_);
|
||||
|
@ -637,7 +639,7 @@ template<typename T> class MutableSpan {
|
|||
/**
|
||||
* Returns a new span to the same underlying memory buffer. No conversions are done.
|
||||
*/
|
||||
template<typename NewT> MutableSpan<NewT> cast() const
|
||||
template<typename NewT> constexpr MutableSpan<NewT> cast() const
|
||||
{
|
||||
BLI_assert((size_ * sizeof(T)) % sizeof(NewT) == 0);
|
||||
int64_t new_size = size_ * sizeof(T) / sizeof(NewT);
|
||||
|
@ -648,7 +650,7 @@ template<typename T> class MutableSpan {
|
|||
/**
|
||||
* Utilities to check that arrays have the same size in debug builds.
|
||||
*/
|
||||
template<typename T1, typename T2> void assert_same_size(const T1 &v1, const T2 &v2)
|
||||
template<typename T1, typename T2> constexpr void assert_same_size(const T1 &v1, const T2 &v2)
|
||||
{
|
||||
UNUSED_VARS_NDEBUG(v1, v2);
|
||||
#ifdef DEBUG
|
||||
|
@ -659,7 +661,7 @@ template<typename T1, typename T2> void assert_same_size(const T1 &v1, const T2
|
|||
}
|
||||
|
||||
template<typename T1, typename T2, typename T3>
|
||||
void assert_same_size(const T1 &v1, const T2 &v2, const T3 &v3)
|
||||
constexpr void assert_same_size(const T1 &v1, const T2 &v2, const T3 &v3)
|
||||
{
|
||||
UNUSED_VARS_NDEBUG(v1, v2, v3);
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -64,7 +64,7 @@ class StringRefBase {
|
|||
const char *data_;
|
||||
int64_t size_;
|
||||
|
||||
StringRefBase(const char *data, const int64_t size) : data_(data), size_(size)
|
||||
constexpr StringRefBase(const char *data, const int64_t size) : data_(data), size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -75,12 +75,12 @@ class StringRefBase {
|
|||
/**
|
||||
* Return the (byte-)length of the referenced string, without any null-terminator.
|
||||
*/
|
||||
int64_t size() const
|
||||
constexpr int64_t size() const
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
bool is_empty() const
|
||||
constexpr bool is_empty() const
|
||||
{
|
||||
return size_ == 0;
|
||||
}
|
||||
|
@ -88,12 +88,12 @@ class StringRefBase {
|
|||
/**
|
||||
* Return a pointer to the start of the string.
|
||||
*/
|
||||
const char *data() const
|
||||
constexpr const char *data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
operator Span<char>() const
|
||||
constexpr operator Span<char>() const
|
||||
{
|
||||
return Span<char>(data_, size_);
|
||||
}
|
||||
|
@ -107,22 +107,22 @@ class StringRefBase {
|
|||
return std::string(data_, static_cast<size_t>(size_));
|
||||
}
|
||||
|
||||
operator std::string_view() const
|
||||
constexpr operator std::string_view() const
|
||||
{
|
||||
return std::string_view(data_, static_cast<size_t>(size_));
|
||||
}
|
||||
|
||||
const char *begin() const
|
||||
constexpr const char *begin() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
const char *end() const
|
||||
constexpr const char *end() const
|
||||
{
|
||||
return data_ + size_;
|
||||
}
|
||||
|
||||
IndexRange index_range() const
|
||||
constexpr IndexRange index_range() const
|
||||
{
|
||||
return IndexRange(size_);
|
||||
}
|
||||
|
@ -165,19 +165,19 @@ class StringRefBase {
|
|||
/**
|
||||
* Returns true when the string begins with the given prefix. Otherwise false.
|
||||
*/
|
||||
bool startswith(StringRef prefix) const;
|
||||
constexpr bool startswith(StringRef prefix) const;
|
||||
|
||||
/**
|
||||
* Returns true when the string ends with the given suffix. Otherwise false.
|
||||
*/
|
||||
bool endswith(StringRef suffix) const;
|
||||
constexpr bool endswith(StringRef suffix) const;
|
||||
|
||||
StringRef substr(int64_t start, const int64_t size) const;
|
||||
constexpr StringRef substr(int64_t start, const int64_t size) const;
|
||||
|
||||
/**
|
||||
* Get the first char in the string. This invokes undefined behavior when the string is empty.
|
||||
*/
|
||||
const char &front() const
|
||||
constexpr const char &front() const
|
||||
{
|
||||
BLI_assert(size_ >= 1);
|
||||
return data_[0];
|
||||
|
@ -186,7 +186,7 @@ class StringRefBase {
|
|||
/**
|
||||
* Get the last char in the string. This invokes undefined behavior when the string is empty.
|
||||
*/
|
||||
const char &back() const
|
||||
constexpr const char &back() const
|
||||
{
|
||||
BLI_assert(size_ >= 1);
|
||||
return data_[size_ - 1];
|
||||
|
@ -196,18 +196,18 @@ class StringRefBase {
|
|||
* The behavior of those functions matches the standard library implementation of
|
||||
* std::string_view.
|
||||
*/
|
||||
int64_t find(char c, int64_t pos = 0) const;
|
||||
int64_t find(StringRef str, int64_t pos = 0) const;
|
||||
int64_t rfind(char c, int64_t pos = INT64_MAX) const;
|
||||
int64_t rfind(StringRef str, int64_t pos = INT64_MAX) const;
|
||||
int64_t find_first_of(StringRef chars, int64_t pos = 0) const;
|
||||
int64_t find_first_of(char c, int64_t pos = 0) const;
|
||||
int64_t find_last_of(StringRef chars, int64_t pos = INT64_MAX) const;
|
||||
int64_t find_last_of(char c, int64_t pos = INT64_MAX) const;
|
||||
int64_t find_first_not_of(StringRef chars, int64_t pos = 0) const;
|
||||
int64_t find_first_not_of(char c, int64_t pos = 0) const;
|
||||
int64_t find_last_not_of(StringRef chars, int64_t pos = INT64_MAX) const;
|
||||
int64_t find_last_not_of(char c, int64_t pos = INT64_MAX) const;
|
||||
constexpr int64_t find(char c, int64_t pos = 0) const;
|
||||
constexpr int64_t find(StringRef str, int64_t pos = 0) const;
|
||||
constexpr int64_t rfind(char c, int64_t pos = INT64_MAX) const;
|
||||
constexpr int64_t rfind(StringRef str, int64_t pos = INT64_MAX) const;
|
||||
constexpr int64_t find_first_of(StringRef chars, int64_t pos = 0) const;
|
||||
constexpr int64_t find_first_of(char c, int64_t pos = 0) const;
|
||||
constexpr int64_t find_last_of(StringRef chars, int64_t pos = INT64_MAX) const;
|
||||
constexpr int64_t find_last_of(char c, int64_t pos = INT64_MAX) const;
|
||||
constexpr int64_t find_first_not_of(StringRef chars, int64_t pos = 0) const;
|
||||
constexpr int64_t find_first_not_of(char c, int64_t pos = 0) const;
|
||||
constexpr int64_t find_last_not_of(StringRef chars, int64_t pos = INT64_MAX) const;
|
||||
constexpr int64_t find_last_not_of(char c, int64_t pos = INT64_MAX) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -216,7 +216,7 @@ class StringRefBase {
|
|||
class StringRefNull : public StringRefBase {
|
||||
|
||||
public:
|
||||
StringRefNull() : StringRefBase("", 0)
|
||||
constexpr StringRefNull() : StringRefBase("", 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ class StringRefNull : public StringRefBase {
|
|||
*/
|
||||
StringRefNull(const char *str) : StringRefBase(str, static_cast<int64_t>(strlen(str)))
|
||||
{
|
||||
BLI_assert(str != NULL);
|
||||
BLI_assert(str != nullptr);
|
||||
BLI_assert(data_[size_] == '\0');
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,7 @@ class StringRefNull : public StringRefBase {
|
|||
* Construct a StringRefNull from a null terminated c-string. This invokes undefined behavior
|
||||
* when the given size is not the correct size of the string.
|
||||
*/
|
||||
StringRefNull(const char *str, const int64_t size) : StringRefBase(str, size)
|
||||
constexpr StringRefNull(const char *str, const int64_t size) : StringRefBase(str, size)
|
||||
{
|
||||
BLI_assert(static_cast<int64_t>(strlen(str)) == size);
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ class StringRefNull : public StringRefBase {
|
|||
/**
|
||||
* Get the char at the given index.
|
||||
*/
|
||||
char operator[](const int64_t index) const
|
||||
constexpr char operator[](const int64_t index) const
|
||||
{
|
||||
BLI_assert(index >= 0);
|
||||
/* Use '<=' instead of just '<', so that the null character can be accessed as well. */
|
||||
|
@ -263,7 +263,7 @@ class StringRefNull : public StringRefBase {
|
|||
*
|
||||
* This is like ->data(), but can only be called on a StringRefNull.
|
||||
*/
|
||||
const char *c_str() const
|
||||
constexpr const char *c_str() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
@ -274,25 +274,26 @@ class StringRefNull : public StringRefBase {
|
|||
*/
|
||||
class StringRef : public StringRefBase {
|
||||
public:
|
||||
StringRef() : StringRefBase(nullptr, 0)
|
||||
constexpr StringRef() : StringRefBase(nullptr, 0)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* StringRefNull can be converted into StringRef, but not the other way around.
|
||||
*/
|
||||
StringRef(StringRefNull other) : StringRefBase(other.data(), other.size())
|
||||
constexpr StringRef(StringRefNull other) : StringRefBase(other.data(), other.size())
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a StringRef from a null-terminated c-string.
|
||||
*/
|
||||
StringRef(const char *str) : StringRefBase(str, str ? static_cast<int64_t>(strlen(str)) : 0)
|
||||
constexpr StringRef(const char *str)
|
||||
: StringRefBase(str, str ? static_cast<int64_t>(std::char_traits<char>::length(str)) : 0)
|
||||
{
|
||||
}
|
||||
|
||||
StringRef(const char *str, const int64_t length) : StringRefBase(str, length)
|
||||
constexpr StringRef(const char *str, const int64_t length) : StringRefBase(str, length)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -300,7 +301,7 @@ class StringRef : public StringRefBase {
|
|||
* Create a StringRef from a start and end pointer. This invokes undefined behavior when the
|
||||
* second point points to a smaller address than the first one.
|
||||
*/
|
||||
StringRef(const char *begin, const char *one_after_end)
|
||||
constexpr StringRef(const char *begin, const char *one_after_end)
|
||||
: StringRefBase(begin, static_cast<int64_t>(one_after_end - begin))
|
||||
{
|
||||
BLI_assert(begin <= one_after_end);
|
||||
|
@ -314,7 +315,8 @@ class StringRef : public StringRefBase {
|
|||
{
|
||||
}
|
||||
|
||||
StringRef(std::string_view view) : StringRefBase(view.data(), static_cast<int64_t>(view.size()))
|
||||
constexpr StringRef(std::string_view view)
|
||||
: StringRefBase(view.data(), static_cast<int64_t>(view.size()))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -323,7 +325,7 @@ class StringRef : public StringRefBase {
|
|||
*
|
||||
* This is similar to std::string_view::remove_prefix.
|
||||
*/
|
||||
StringRef drop_prefix(const int64_t n) const
|
||||
constexpr StringRef drop_prefix(const int64_t n) const
|
||||
{
|
||||
BLI_assert(n >= 0);
|
||||
BLI_assert(n <= size_);
|
||||
|
@ -334,7 +336,7 @@ class StringRef : public StringRefBase {
|
|||
* Return a new StringRef with the given prefix being skipped. This invokes undefined behavior if
|
||||
* the string does not begin with the given prefix.
|
||||
*/
|
||||
StringRef drop_prefix(StringRef prefix) const
|
||||
constexpr StringRef drop_prefix(StringRef prefix) const
|
||||
{
|
||||
BLI_assert(this->startswith(prefix));
|
||||
return this->drop_prefix(prefix.size());
|
||||
|
@ -345,7 +347,7 @@ class StringRef : public StringRefBase {
|
|||
*
|
||||
* This is similar to std::string_view::remove_suffix.
|
||||
*/
|
||||
StringRef drop_suffix(const int64_t n) const
|
||||
constexpr StringRef drop_suffix(const int64_t n) const
|
||||
{
|
||||
BLI_assert(n >= 0);
|
||||
BLI_assert(n <= size_);
|
||||
|
@ -355,7 +357,7 @@ class StringRef : public StringRefBase {
|
|||
/**
|
||||
* Get the char at the given index.
|
||||
*/
|
||||
char operator[](int64_t index) const
|
||||
constexpr char operator[](int64_t index) const
|
||||
{
|
||||
BLI_assert(index >= 0);
|
||||
BLI_assert(index < size_);
|
||||
|
@ -391,7 +393,7 @@ inline std::string operator+(StringRef a, StringRef b)
|
|||
* not a problem when std::string_view is only used at api boundaries. To compare a StringRef and a
|
||||
* std::string_view, one should convert the std::string_view to StringRef (which is very cheap).
|
||||
* Ideally, we only use StringRef in our code to avoid this problem altogether. */
|
||||
inline bool operator==(StringRef a, StringRef b)
|
||||
constexpr inline bool operator==(StringRef a, StringRef b)
|
||||
{
|
||||
if (a.size() != b.size()) {
|
||||
return false;
|
||||
|
@ -399,27 +401,27 @@ inline bool operator==(StringRef a, StringRef b)
|
|||
return STREQLEN(a.data(), b.data(), (size_t)a.size());
|
||||
}
|
||||
|
||||
inline bool operator!=(StringRef a, StringRef b)
|
||||
constexpr inline bool operator!=(StringRef a, StringRef b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
inline bool operator<(StringRef a, StringRef b)
|
||||
constexpr inline bool operator<(StringRef a, StringRef b)
|
||||
{
|
||||
return std::string_view(a) < std::string_view(b);
|
||||
}
|
||||
|
||||
inline bool operator>(StringRef a, StringRef b)
|
||||
constexpr inline bool operator>(StringRef a, StringRef b)
|
||||
{
|
||||
return std::string_view(a) > std::string_view(b);
|
||||
}
|
||||
|
||||
inline bool operator<=(StringRef a, StringRef b)
|
||||
constexpr inline bool operator<=(StringRef a, StringRef b)
|
||||
{
|
||||
return std::string_view(a) <= std::string_view(b);
|
||||
}
|
||||
|
||||
inline bool operator>=(StringRef a, StringRef b)
|
||||
constexpr inline bool operator>=(StringRef a, StringRef b)
|
||||
{
|
||||
return std::string_view(a) >= std::string_view(b);
|
||||
}
|
||||
|
@ -427,7 +429,7 @@ inline bool operator>=(StringRef a, StringRef b)
|
|||
/**
|
||||
* Return true when the string starts with the given prefix.
|
||||
*/
|
||||
inline bool StringRefBase::startswith(StringRef prefix) const
|
||||
constexpr inline bool StringRefBase::startswith(StringRef prefix) const
|
||||
{
|
||||
if (size_ < prefix.size_) {
|
||||
return false;
|
||||
|
@ -443,7 +445,7 @@ inline bool StringRefBase::startswith(StringRef prefix) const
|
|||
/**
|
||||
* Return true when the string ends with the given suffix.
|
||||
*/
|
||||
inline bool StringRefBase::endswith(StringRef suffix) const
|
||||
constexpr inline bool StringRefBase::endswith(StringRef suffix) const
|
||||
{
|
||||
if (size_ < suffix.size_) {
|
||||
return false;
|
||||
|
@ -460,8 +462,8 @@ inline bool StringRefBase::endswith(StringRef suffix) const
|
|||
/**
|
||||
* Return a new #StringRef containing only a sub-string of the original string.
|
||||
*/
|
||||
inline StringRef StringRefBase::substr(const int64_t start,
|
||||
const int64_t max_size = INT64_MAX) const
|
||||
constexpr inline StringRef StringRefBase::substr(const int64_t start,
|
||||
const int64_t max_size = INT64_MAX) const
|
||||
{
|
||||
BLI_assert(max_size >= 0);
|
||||
BLI_assert(start >= 0);
|
||||
|
@ -469,7 +471,7 @@ inline StringRef StringRefBase::substr(const int64_t start,
|
|||
return StringRef(data_ + start, substr_size);
|
||||
}
|
||||
|
||||
inline int64_t index_or_npos_to_int64(size_t index)
|
||||
constexpr inline int64_t index_or_npos_to_int64(size_t index)
|
||||
{
|
||||
/* The compiler will probably optimize this check away. */
|
||||
if (index == std::string_view::npos) {
|
||||
|
@ -478,62 +480,62 @@ inline int64_t index_or_npos_to_int64(size_t index)
|
|||
return static_cast<int64_t>(index);
|
||||
}
|
||||
|
||||
inline int64_t StringRefBase::find(char c, int64_t pos) const
|
||||
constexpr inline int64_t StringRefBase::find(char c, int64_t pos) const
|
||||
{
|
||||
BLI_assert(pos >= 0);
|
||||
return index_or_npos_to_int64(std::string_view(*this).find(c, static_cast<size_t>(pos)));
|
||||
}
|
||||
|
||||
inline int64_t StringRefBase::find(StringRef str, int64_t pos) const
|
||||
constexpr inline int64_t StringRefBase::find(StringRef str, int64_t pos) const
|
||||
{
|
||||
BLI_assert(pos >= 0);
|
||||
return index_or_npos_to_int64(std::string_view(*this).find(str, static_cast<size_t>(pos)));
|
||||
}
|
||||
|
||||
inline int64_t StringRefBase::find_first_of(StringRef chars, int64_t pos) const
|
||||
constexpr inline int64_t StringRefBase::find_first_of(StringRef chars, int64_t pos) const
|
||||
{
|
||||
BLI_assert(pos >= 0);
|
||||
return index_or_npos_to_int64(
|
||||
std::string_view(*this).find_first_of(chars, static_cast<size_t>(pos)));
|
||||
}
|
||||
|
||||
inline int64_t StringRefBase::find_first_of(char c, int64_t pos) const
|
||||
constexpr inline int64_t StringRefBase::find_first_of(char c, int64_t pos) const
|
||||
{
|
||||
return this->find_first_of(StringRef(&c, 1), pos);
|
||||
}
|
||||
|
||||
inline int64_t StringRefBase::find_last_of(StringRef chars, int64_t pos) const
|
||||
constexpr inline int64_t StringRefBase::find_last_of(StringRef chars, int64_t pos) const
|
||||
{
|
||||
BLI_assert(pos >= 0);
|
||||
return index_or_npos_to_int64(
|
||||
std::string_view(*this).find_last_of(chars, static_cast<size_t>(pos)));
|
||||
}
|
||||
|
||||
inline int64_t StringRefBase::find_last_of(char c, int64_t pos) const
|
||||
constexpr inline int64_t StringRefBase::find_last_of(char c, int64_t pos) const
|
||||
{
|
||||
return this->find_last_of(StringRef(&c, 1), pos);
|
||||
}
|
||||
|
||||
inline int64_t StringRefBase::find_first_not_of(StringRef chars, int64_t pos) const
|
||||
constexpr inline int64_t StringRefBase::find_first_not_of(StringRef chars, int64_t pos) const
|
||||
{
|
||||
BLI_assert(pos >= 0);
|
||||
return index_or_npos_to_int64(
|
||||
std::string_view(*this).find_first_not_of(chars, static_cast<size_t>(pos)));
|
||||
}
|
||||
|
||||
inline int64_t StringRefBase::find_first_not_of(char c, int64_t pos) const
|
||||
constexpr inline int64_t StringRefBase::find_first_not_of(char c, int64_t pos) const
|
||||
{
|
||||
return this->find_first_not_of(StringRef(&c, 1), pos);
|
||||
}
|
||||
|
||||
inline int64_t StringRefBase::find_last_not_of(StringRef chars, int64_t pos) const
|
||||
constexpr inline int64_t StringRefBase::find_last_not_of(StringRef chars, int64_t pos) const
|
||||
{
|
||||
BLI_assert(pos >= 0);
|
||||
return index_or_npos_to_int64(
|
||||
std::string_view(*this).find_last_not_of(chars, static_cast<size_t>(pos)));
|
||||
}
|
||||
|
||||
inline int64_t StringRefBase::find_last_not_of(char c, int64_t pos) const
|
||||
constexpr inline int64_t StringRefBase::find_last_not_of(char c, int64_t pos) const
|
||||
{
|
||||
return this->find_last_not_of(StringRef(&c, 1), pos);
|
||||
}
|
||||
|
|
|
@ -140,4 +140,11 @@ TEST(index_range, AsSpan)
|
|||
EXPECT_EQ(span[3], 7);
|
||||
}
|
||||
|
||||
TEST(index_range, constexpr_)
|
||||
{
|
||||
constexpr IndexRange range = IndexRange(1, 1);
|
||||
std::array<int, range[0]> compiles = {1};
|
||||
BLI_STATIC_ASSERT(range.size() == 1, "");
|
||||
EXPECT_EQ(compiles[0], 1);
|
||||
}
|
||||
} // namespace blender::tests
|
||||
|
|
|
@ -337,4 +337,19 @@ TEST(span, MutableReverseIterator)
|
|||
EXPECT_EQ_ARRAY(src.data(), Span({14, 15, 16, 17}).data(), 4);
|
||||
}
|
||||
|
||||
TEST(span, constexpr_)
|
||||
{
|
||||
static constexpr std::array<int, 3> src = {3, 2, 1};
|
||||
constexpr Span<int> span(src);
|
||||
BLI_STATIC_ASSERT(span[2] == 1, "");
|
||||
BLI_STATIC_ASSERT(span.size() == 3, "");
|
||||
BLI_STATIC_ASSERT(span.slice(1, 2).size() == 2, "");
|
||||
BLI_STATIC_ASSERT(span.has_duplicates__linear_search() == false, "");
|
||||
|
||||
std::integral_constant<bool, span.first_index(1) == 2> ic;
|
||||
BLI_STATIC_ASSERT(ic.value, "");
|
||||
|
||||
EXPECT_EQ(span.slice(1, 2).size(), 2);
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
||||
|
|
|
@ -298,4 +298,12 @@ TEST(string_ref, ToStringView)
|
|||
EXPECT_EQ(view, "hello");
|
||||
}
|
||||
|
||||
TEST(string_ref, constexpr_)
|
||||
{
|
||||
constexpr StringRef sref("World");
|
||||
BLI_STATIC_ASSERT(sref[2] == 'r', "");
|
||||
BLI_STATIC_ASSERT(sref.size() == 5, "");
|
||||
std::array<int, static_cast<std::size_t>(sref.find_first_of('o'))> compiles = {1};
|
||||
EXPECT_EQ(compiles[0], 1);
|
||||
}
|
||||
} // namespace blender::tests
|
||||
|
|
Loading…
Reference in New Issue