From: Wolfgang Bangerth Date: Sat, 25 Nov 2023 05:12:33 +0000 (-0700) Subject: Better document Lazy and fix move semantics. X-Git-Tag: relicensing~276^2~1 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d75a35fa40b976c1400cf73a2883d1f58ecc93a;p=dealii.git Better document Lazy and fix move semantics. --- diff --git a/include/deal.II/base/lazy.h b/include/deal.II/base/lazy.h index 01653affbf..b3774f3bbe 100644 --- a/include/deal.II/base/lazy.h +++ b/include/deal.II/base/lazy.h @@ -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::Lazy(const Lazy &other) template inline Lazy::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 does *not* result in an empty + // std::optional 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 inline Lazy & Lazy::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 does *not* result in an empty + // std::optional 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::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()); }