Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2021-03-17 17:26:17 +0300
committerJacques Lucke <jacques@blender.org>2021-03-17 17:27:31 +0300
commitbf620020f135eab149b6327b79de8b378d99be7e (patch)
tree9b1fe60a60faa277e3abbd4a95d729b1cf29723c
parent256da1c4b97224bc93b4d685896fabc9399639c5 (diff)
BLI: improve implicit conversions of spans
Some conversions that should work did not work before. For example, `MutableSpan<int *> -> MutableSpan<const int *>`.
-rw-r--r--source/blender/blenlib/BLI_span.hh24
-rw-r--r--source/blender/blenlib/tests/BLI_span_test.cc12
2 files changed, 32 insertions, 4 deletions
diff --git a/source/blender/blenlib/BLI_span.hh b/source/blender/blenlib/BLI_span.hh
index 5f55efe3f63..f4960df8ab9 100644
--- a/source/blender/blenlib/BLI_span.hh
+++ b/source/blender/blenlib/BLI_span.hh
@@ -132,12 +132,11 @@ template<typename T> class Span {
}
/**
- * Support implicit conversions like the ones below:
+ * Support implicit conversions like the one below:
* Span<T *> -> Span<const T *>
*/
-
template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<U, T>> * = nullptr>
- constexpr Span(Span<U> array) : data_(static_cast<const T *>(array.data())), size_(array.size())
+ constexpr Span(Span<U> span) : data_(static_cast<const T *>(span.data())), size_(span.size())
{
}
@@ -467,11 +466,27 @@ template<typename T> class MutableSpan {
{
}
+ /**
+ * Support implicit conversions like the one below:
+ * MutableSpan<T *> -> MutableSpan<const T *>
+ */
+ template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<U, T>> * = nullptr>
+ constexpr MutableSpan(MutableSpan<U> span)
+ : data_(static_cast<T *>(span.data())), size_(span.size())
+ {
+ }
+
constexpr operator Span<T>() const
{
return Span<T>(data_, size_);
}
+ template<typename U, typename std::enable_if_t<is_span_convertible_pointer_v<T, U>> * = nullptr>
+ constexpr operator Span<U>() const
+ {
+ return Span<U>(static_cast<const U *>(data_), size_);
+ }
+
/**
* Returns the number of elements in the array.
*/
@@ -653,12 +668,13 @@ template<typename T> class MutableSpan {
/**
* Returns a new span to the same underlying memory buffer. No conversions are done.
+ * The caller is responsible for making sure that the type cast is valid.
*/
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);
- return MutableSpan<NewT>(reinterpret_cast<NewT *>(data_), new_size);
+ return MutableSpan<NewT>((NewT *)data_, new_size);
}
};
diff --git a/source/blender/blenlib/tests/BLI_span_test.cc b/source/blender/blenlib/tests/BLI_span_test.cc
index 002c97b0c7d..f611529b47e 100644
--- a/source/blender/blenlib/tests/BLI_span_test.cc
+++ b/source/blender/blenlib/tests/BLI_span_test.cc
@@ -392,4 +392,16 @@ TEST(span, Constexpr)
EXPECT_EQ(span.slice(1, 2).size(), 2);
}
+TEST(span, ImplicitConversions)
+{
+ BLI_STATIC_ASSERT((std::is_convertible_v<MutableSpan<int>, Span<int>>), "");
+ BLI_STATIC_ASSERT((std::is_convertible_v<Span<int *>, Span<const int *>>), "");
+ BLI_STATIC_ASSERT((std::is_convertible_v<MutableSpan<int *>, Span<int *>>), "");
+ BLI_STATIC_ASSERT((std::is_convertible_v<MutableSpan<int *>, Span<const int *>>), "");
+ BLI_STATIC_ASSERT((std::is_convertible_v<MutableSpan<int *>, MutableSpan<const int *>>), "");
+ BLI_STATIC_ASSERT((!std::is_convertible_v<MutableSpan<const int *>, MutableSpan<int *>>), "");
+ BLI_STATIC_ASSERT((!std::is_convertible_v<Span<const int *>, Span<int *>>), "");
+ BLI_STATIC_ASSERT((!std::is_convertible_v<Span<int *>, MutableSpan<const int *>>), "");
+}
+
} // namespace blender::tests