[Bf-blender-cvs] [5b9cad04c61] virtual-array-attributes: add virtual array for container

Jacques Lucke noreply at git.blender.org
Mon Apr 12 18:27:52 CEST 2021


Commit: 5b9cad04c61585548512c461d17043e0d4d4d7e9
Author: Jacques Lucke
Date:   Sat Apr 10 13:14:42 2021 +0200
Branches: virtual-array-attributes
https://developer.blender.org/rB5b9cad04c61585548512c461d17043e0d4d4d7e9

add virtual array for container

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

M	source/blender/blenlib/BLI_virtual_array.hh
M	source/blender/blenlib/tests/BLI_virtual_array_test.cc

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

diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh
index f9b0aaa7de6..371703d4038 100644
--- a/source/blender/blenlib/BLI_virtual_array.hh
+++ b/source/blender/blenlib/BLI_virtual_array.hh
@@ -145,35 +145,65 @@ template<typename T> class VArray {
 };
 
 /**
- * A virtual array implementation for a span. This class is final so that it can be devirtualized
- * by the compiler in some cases (e.g. when #devirtualize_varray is used).
+ * A virtual array implementation for a span. Methods in this class are final so that it can be
+ * devirtualized by the compiler in some cases (e.g. when #devirtualize_varray is used).
  */
-template<typename T> class VArrayForSpan final : public VArray<T> {
+template<typename T> class VArrayForSpan : public VArray<T> {
  private:
-  const T *data_;
+  const T *data_ = nullptr;
 
  public:
   VArrayForSpan(const Span<T> data) : VArray<T>(data.size()), data_(data.data())
   {
   }
 
+  /* When this constructor is used, the #set_data method has to be used as well. */
+  VArrayForSpan(const int64_t size) : VArray<T>(size)
+  {
+  }
+
  protected:
-  T get_impl(const int64_t index) const override
+  /* Can be used when the data pointer is not ready when the constructor is called. */
+  void set_data(const T *data)
+  {
+    data_ = data;
+  }
+
+  T get_impl(const int64_t index) const final
   {
     return data_[index];
   }
 
-  bool is_span_impl() const override
+  bool is_span_impl() const final
   {
     return true;
   }
 
-  Span<T> get_span_impl() const override
+  Span<T> get_span_impl() const final
   {
     return Span<T>(data_, this->size_);
   }
 };
 
+/**
+ * A variant of `VArrayForSpan` that owns the underlying data.
+ * The `Container` type has to implement a `size()` and `data()` method.
+ * The `data()` method has to return a pointer to the first element in the continuous array of
+ * elements.
+ */
+template<typename Container, typename T = typename Container::value_type>
+class VArrayForArrayContainer : public VArrayForSpan<T> {
+ private:
+  Container container_;
+
+ public:
+  VArrayForArrayContainer(Container container)
+      : VArrayForSpan<T>((int64_t)container.size()), container_(std::move(container))
+  {
+    this->set_data(container_.data());
+  }
+};
+
 /**
  * A virtual array implementation that returns the same value for every index. This class is final
  * so that it can be devirtualized by the compiler in some cases (e.g. when #devirtualize_varray is
diff --git a/source/blender/blenlib/tests/BLI_virtual_array_test.cc b/source/blender/blenlib/tests/BLI_virtual_array_test.cc
index ac25229cd69..0f568f63d79 100644
--- a/source/blender/blenlib/tests/BLI_virtual_array_test.cc
+++ b/source/blender/blenlib/tests/BLI_virtual_array_test.cc
@@ -1,6 +1,9 @@
 /* Apache License, Version 2.0 */
 
+#include "BLI_array.hh"
 #include "BLI_strict_flags.h"
+#include "BLI_vector.hh"
+#include "BLI_vector_set.hh"
 #include "BLI_virtual_array.hh"
 #include "testing/testing.h"
 
@@ -28,4 +31,68 @@ TEST(virtual_array, ForSingle)
   EXPECT_TRUE(varray.is_single());
 }
 
+TEST(virtual_array, ForArray)
+{
+  Array<int> array = {1, 2, 3, 5, 8};
+  {
+    VArrayForArrayContainer varray{array};
+    EXPECT_EQ(varray.size(), 5);
+    EXPECT_EQ(varray[0], 1);
+    EXPECT_EQ(varray[2], 3);
+    EXPECT_EQ(varray[3], 5);
+    EXPECT_TRUE(varray.is_span());
+  }
+  {
+    VArrayForArrayContainer varray{std::move(array)};
+    EXPECT_EQ(varray.size(), 5);
+    EXPECT_EQ(varray[0], 1);
+    EXPECT_EQ(varray[2], 3);
+    EXPECT_EQ(varray[3], 5);
+    EXPECT_TRUE(varray.is_span());
+  }
+  {
+    VArrayForArrayContainer varray{array}; /* NOLINT: bugprone-use-after-move */
+    EXPECT_TRUE(varray.is_empty());
+  }
+}
+
+TEST(virtual_array, ForVector)
+{
+  Vector<int> vector = {9, 8, 7, 6};
+  VArrayForArrayContainer varray{std::move(vector)};
+  EXPECT_EQ(varray.size(), 4);
+  EXPECT_EQ(varray[0], 9);
+  EXPECT_EQ(varray[3], 6);
+}
+
+TEST(virtual_array, ForStdVector)
+{
+  std::vector<int> vector = {5, 6, 7, 8};
+  VArrayForArrayContainer varray{std::move(vector)};
+  EXPECT_EQ(varray.size(), 4);
+  EXPECT_EQ(varray[0], 5);
+  EXPECT_EQ(varray[1], 6);
+}
+
+TEST(virtual_array, ForStdArray)
+{
+  std::array<int, 4> array = {2, 3, 4, 5};
+  VArrayForArrayContainer varray{array};
+  EXPECT_EQ(varray.size(), 4);
+  EXPECT_EQ(varray[0], 2);
+  EXPECT_EQ(varray[1], 3);
+}
+
+TEST(virtual_array, ForVectorSet)
+{
+  VectorSet<int> vector_set = {5, 3, 7, 3, 3, 5, 1};
+  VArrayForArrayContainer varray{std::move(vector_set)};
+  EXPECT_TRUE(vector_set.is_empty()); /* NOLINT: bugprone-use-after-move. */
+  EXPECT_EQ(varray.size(), 4);
+  EXPECT_EQ(varray[0], 5);
+  EXPECT_EQ(varray[1], 3);
+  EXPECT_EQ(varray[2], 7);
+  EXPECT_EQ(varray[3], 1);
+}
+
 }  // namespace blender::tests



More information about the Bf-blender-cvs mailing list