From efc56fe479ccc17b30a92a5a25901692abb7fd0b Mon Sep 17 00:00:00 2001
From: Tobias Leibner <tobias.leibner@googlemail.com>
Date: Thu, 3 Dec 2020 13:04:42 +0100
Subject: [PATCH] [container-interface] add assignment operators

---
 dune/xt/la/container/container-interface.hh | 13 +++++++++++++
 dune/xt/la/container/vector-interface.hh    | 16 ++++++++--------
 dune/xt/test/la/container.tpl               |  2 ++
 dune/xt/test/la/container_vector.tpl        |  9 ++++++++-
 4 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/dune/xt/la/container/container-interface.hh b/dune/xt/la/container/container-interface.hh
index 24e0c2409..ccb1ba745 100644
--- a/dune/xt/la/container/container-interface.hh
+++ b/dune/xt/la/container/container-interface.hh
@@ -98,6 +98,7 @@ template <class TraitsImp, class ScalarImp = typename TraitsImp::ScalarType>
 class ContainerInterface : public Common::CRTPInterface<ContainerInterface<TraitsImp, ScalarImp>, TraitsImp>
 {
   using CRTP = Common::CRTPInterface<ContainerInterface<TraitsImp, ScalarImp>, TraitsImp>;
+  using ThisType = ContainerInterface;
 
 public:
   using typename CRTP::derived_type;
@@ -110,6 +111,18 @@ public:
 
   virtual ~ContainerInterface() {}
 
+  ThisType& operator=(const ThisType& other)
+  {
+    this->as_imp() = other.as_imp();
+    return *this;
+  }
+
+  ThisType& operator=(ThisType&& other)
+  {
+    this->as_imp() = std::move(other.as_imp());
+    return *this;
+  }
+
   /// \name Have to be implemented by a derived class!
   /// \{
 
diff --git a/dune/xt/la/container/vector-interface.hh b/dune/xt/la/container/vector-interface.hh
index 73cea343d..618e864e3 100644
--- a/dune/xt/la/container/vector-interface.hh
+++ b/dune/xt/la/container/vector-interface.hh
@@ -93,6 +93,14 @@ public:
     return this->as_imp();
   }
 
+  template <class T, class S>
+  derived_type& operator=(const VectorInterface<T, S>& other)
+  {
+    for (size_t ii = 0; ii < size(); ++ii)
+      set_entry(ii, other.get_entry(ii));
+    return this->as_imp();
+  }
+
   /// \name Have to be implemented by a derived class in addition to the ones required by ContainerInterface!
   /// \{
 
@@ -456,14 +464,6 @@ public:
     return dot(other);
   }
 
-  template <class T, class S>
-  derived_type& operator=(const VectorInterface<T, S>& other)
-  {
-    for (size_t ii = 0; ii < size(); ++ii)
-      set_entry(ii, other.get_entry(ii));
-    return this->as_imp();
-  }
-
   /**
    *  \brief  Adds another vector to this, in-place variant.
    *  \param  other The second summand.
diff --git a/dune/xt/test/la/container.tpl b/dune/xt/test/la/container.tpl
index c93196a08..5071b9ad1 100644
--- a/dune/xt/test/la/container.tpl
+++ b/dune/xt/test/la/container.tpl
@@ -67,6 +67,8 @@ struct ContainerTest{{NAME}} : public ::testing::Test
     ContainerImp i_deep_copy = i_by_size.copy();
     i_by_size.scal(I_ScalarType(1));
     i_by_size.axpy(I_ScalarType(1), i_deep_copy);
+    i_by_size = d_copy_constructor;
+    EXPECT_TRUE(XT::Common::FloatCmp::eq(d_by_size, d_copy_constructor));
   } // void fulfills_interface() const
 }; // struct ContainerTest
 
diff --git a/dune/xt/test/la/container_vector.tpl b/dune/xt/test/la/container_vector.tpl
index c7dd6cccc..039f1cca7 100644
--- a/dune/xt/test/la/container_vector.tpl
+++ b/dune/xt/test/la/container_vector.tpl
@@ -99,8 +99,10 @@ struct LaContainerVectorTest_{{T_NAME}} : public ::testing::Test
     // * of the vector as the interface
     VectorImp d_by_size_2(dim);
     VectorImp d_by_size_and_value_2(dim, D_ScalarType(1));
+    d_ones = VectorImp(dim, I_ScalarType(1));
     InterfaceType& i_by_size = static_cast<InterfaceType&>(d_by_size_2);
     InterfaceType& i_by_size_and_value = static_cast<InterfaceType&>(d_by_size_and_value_2);
+    InterfaceType& i_ones = static_cast<InterfaceType&>(d_ones);
     EXPECT_TRUE(i_by_size.almost_equal(d_by_size_2));
     i_by_size_and_value.scal(I_ScalarType(0));
     EXPECT_TRUE(i_by_size_and_value.almost_equal(d_by_size_2));
@@ -112,7 +114,6 @@ struct LaContainerVectorTest_{{T_NAME}} : public ::testing::Test
     EXPECT_DOUBLE_OR_COMPLEX_EQ(I_RealType(0), i_l2_norm);
     I_ScalarType i_sup_norm = i_by_size.sup_norm();
     EXPECT_DOUBLE_OR_COMPLEX_EQ(I_RealType(0), i_sup_norm);
-    VectorImp i_ones(dim, I_ScalarType(1));
     std::pair<size_t, I_ScalarType> i_amax = i_ones.amax();
     EXPECT_EQ(0, i_amax.first);
     EXPECT_DOUBLE_OR_COMPLEX_EQ(I_RealType(1), i_amax.second);
@@ -128,6 +129,12 @@ struct LaContainerVectorTest_{{T_NAME}} : public ::testing::Test
     EXPECT_TRUE(i_subtracted.almost_equal(d_by_size_and_value_2));
     i_subtracted.isub(d_by_size_2);
     EXPECT_TRUE(i_subtracted.almost_equal(i_ones));
+    // check operator= works for interface
+    i_ones = VectorImp(dim, D_ScalarType(1));
+    d_by_size_and_value = VectorImp(dim, D_ScalarType(0));
+    EXPECT_TRUE(XT::Common::FloatCmp::ne(d_ones, d_by_size_and_value));
+    i_ones = d_by_size_and_value;
+    EXPECT_TRUE(XT::Common::FloatCmp::eq(d_ones, d_by_size_and_value));
   } // void fulfills_interface() const
 
   void produces_correct_results() const
-- 
GitLab