From 2d05f6b5b47cb7bcc755d9fcd7fd9a406da07265 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com>
Date: Thu, 24 Jun 2021 13:22:02 +0200
Subject: [PATCH] Improve Vector's API

One can now build a Vector from an Array.
In that case the Vector will no more perform shallow copies.
---
 src/algebra/Vector.hpp | 61 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 53 insertions(+), 8 deletions(-)

diff --git a/src/algebra/Vector.hpp b/src/algebra/Vector.hpp
index 089efa633..e9eace62a 100644
--- a/src/algebra/Vector.hpp
+++ b/src/algebra/Vector.hpp
@@ -17,12 +17,23 @@ class Vector   // LCOV_EXCL_LINE
 
  private:
   Array<DataType> m_values;
+  const bool m_deep_copies;
+
   static_assert(std::is_same_v<typename decltype(m_values)::index_type, index_type>);
 
   // Allows const version to access our data
   friend Vector<std::add_const_t<DataType>>;
 
  public:
+  friend std::ostream&
+  operator<<(std::ostream& os, const Vector& x)
+  {
+    for (size_t i = 0; i < x.size(); ++i) {
+      os << ' ' << x[i];
+    }
+    return os;
+  }
+
   friend Vector<std::remove_const_t<DataType>>
   copy(const Vector& x)
   {
@@ -56,7 +67,7 @@ class Vector   // LCOV_EXCL_LINE
 
     // Does not use parallel_for to preserve sum order
     for (index_type i = 0; i < x.size(); ++i) {
-      sum += x.m_values[i] * y.m_values[i];
+      sum += x[i] * y[i];
     }
 
     return sum;
@@ -152,20 +163,49 @@ class Vector   // LCOV_EXCL_LINE
 
   template <typename DataType2>
   PUGS_INLINE Vector&
-  operator=(const Vector<DataType2>& vector) noexcept
+  operator=(const Vector<DataType2>& x) noexcept
   {
-    m_values = vector.m_values;
+    // ensures that DataType is the same as source DataType2
+    static_assert(std::is_same<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>(),
+                  "Cannot assign Vector of different type");
+    // ensures that const is not lost through copy
+    static_assert(((std::is_const<DataType2>() and std::is_const<DataType>()) or not std::is_const<DataType2>()),
+                  "Cannot assign Vector of const to Vector of non-const");
+
+    if (m_deep_copies) {
+      copy_to(x.m_values, m_values);
+    } else {
+      m_values = x.m_values;
+    }
     return *this;
   }
 
   PUGS_INLINE
-  Vector& operator=(const Vector&) = default;
+  Vector&
+  operator=(const Vector& x)
+  {
+    if (m_deep_copies) {
+      copy_to(x.m_values, m_values);
+    } else {
+      m_values = x.m_values;
+    }
+    return *this;
+  }
 
   PUGS_INLINE
-  Vector& operator=(Vector&&) = default;
+  Vector&
+  operator=(Vector&& x)
+  {
+    if (m_deep_copies) {
+      copy_to(x.m_values, m_values);
+    } else {
+      m_values = x.m_values;
+    }
+    return *this;
+  }
 
   template <typename DataType2>
-  Vector(const Vector<DataType2>& x)
+  Vector(const Vector<DataType2>& x) : m_deep_copies{x.m_deep_copies}
   {
     // ensures that DataType is the same as source DataType2
     static_assert(std::is_same<std::remove_const_t<DataType>, std::remove_const_t<DataType2>>(),
@@ -174,14 +214,19 @@ class Vector   // LCOV_EXCL_LINE
     static_assert(((std::is_const<DataType2>() and std::is_const<DataType>()) or not std::is_const<DataType2>()),
                   "Cannot assign Vector of const to Vector of non-const");
 
-    this->operator=(x);
+    m_values = x.m_values;
+  }
+
+  explicit Vector(const Array<DataType>& values) : m_deep_copies{true}
+  {
+    m_values = values;
   }
 
   Vector(const Vector&) = default;
 
   Vector(Vector&&) = default;
 
-  Vector(size_t size) : m_values{size} {}
+  Vector(size_t size) : m_values{size}, m_deep_copies{false} {}
   ~Vector() = default;
 };
 
-- 
GitLab