[Bf-blender-cvs] [bf620020f13] master: BLI: improve implicit conversions of spans

Jacques Lucke noreply at git.blender.org
Wed Mar 17 15:27:39 CET 2021


Commit: bf620020f135eab149b6327b79de8b378d99be7e
Author: Jacques Lucke
Date:   Wed Mar 17 15:26:17 2021 +0100
Branches: master
https://developer.blender.org/rBbf620020f135eab149b6327b79de8b378d99be7e

BLI: improve implicit conversions of spans

Some conversions that should work did not work before.
For example, `MutableSpan<int *> -> MutableSpan<const int *>`.

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

M	source/blender/blenlib/BLI_span.hh
M	source/blender/blenlib/tests/BLI_span_test.cc

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

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



More information about the Bf-blender-cvs mailing list