]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Better document Lazy<T> and fix move semantics.
authorWolfgang Bangerth <bangerth@colostate.edu>
Sat, 25 Nov 2023 05:12:33 +0000 (22:12 -0700)
committerWolfgang Bangerth <bangerth@colostate.edu>
Sat, 25 Nov 2023 05:12:33 +0000 (22:12 -0700)
include/deal.II/base/lazy.h

index 01653affbfb96eaaa1c132bddf0994ea0cc22129..b3774f3bbedb400b38207b2cf679d25142b80292 100644 (file)
@@ -88,26 +88,40 @@ public:
 
 
   /**
-   * Copy constructor.
+   * Copy constructor. If the `other` object contains an initialized
+   * value, then that value will be copied into the current object. If the
+   * `other` object is uninitialized, then the current object will be as well.
    */
   Lazy(const Lazy &other);
 
 
   /**
-   * Move constructor.
+   * Move constructor. If the `other` object contains an initialized
+   * value, then that value will be moved into the current object, and the
+   * `other` object will end up being empty (as if default initialized). If the
+   * `other` object is uninitialized, then the current object will be as well.
    */
   Lazy(Lazy &&other) noexcept;
 
 
   /**
-   * Copy assignment.
+   * Copy assignment. If the `other` object contains an initialized
+   * value, then that value will be copied into the current object. If the
+   * `other` object is uninitialized, then the current object will be as well.
+   *
+   * Any content of the current object is lost in the assignment.
    */
   Lazy &
   operator=(const Lazy &other);
 
 
   /**
-   * Move assignment.
+   * Move assignment. If the `other` object contains an initialized
+   * value, then that value will be moved into the current object, and the
+   * `other` object will end up being empty (as if default initialized). If the
+   * `other` object is uninitialized, then the current object will be as well.
+   *
+   * Any content of the current object is lost in the move assignment.
    */
   Lazy &
   operator=(Lazy &&other) noexcept;
@@ -256,9 +270,17 @@ inline Lazy<T>::Lazy(const Lazy &other)
 
 template <typename T>
 inline Lazy<T>::Lazy(Lazy &&other) noexcept
-  : object(other.object)
+  : object(std::move(other.object))
 {
   object_is_initialized.store(other.object_is_initialized.load());
+
+  // Mark the other object as uninitialized. This is marginally non-trivial
+  // because moving from std::optional<T> does *not* result in an empty
+  // std::optional<T> but instead one that does contain a T, but one that
+  // has been moved from -- typically something akin to a default-initialized
+  // T. That seems undesirable, so reset everything to an empty state.
+  other.object_is_initialized.store(false);
+  other.object.reset();
 }
 
 
@@ -276,8 +298,17 @@ template <typename T>
 inline Lazy<T> &
 Lazy<T>::operator=(Lazy &&other) noexcept
 {
-  object = other.object;
+  object = std::move(other.object);
   object_is_initialized.store(other.object_is_initialized.load());
+
+  // Mark the other object as uninitialized. This is marginally non-trivial
+  // because moving from std::optional<T> does *not* result in an empty
+  // std::optional<T> but instead one that does contain a T, but one that
+  // has been moved from -- typically something akin to a default-initialized
+  // T. That seems undesirable, so reset everything to an empty state.
+  other.object_is_initialized.store(false);
+  other.object.reset();
+
   return *this;
 }
 
@@ -363,7 +394,7 @@ Lazy<T>::has_value() const
   // semantics. But just in case let's check the object.has_value() boolean
   // as well:
   //
-  return object_is_initialized && object.has_value();
+  return (object_is_initialized && object.has_value());
 }
 
 

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.