SpECTRE Documentation Coverage Report
Current view: top level - DataStructures - MaybeOwned.hpp Coverage Total Hit
Commit: a37d7b3c1803b88b537d2aef1c27ca5e6b499398 Lines: 48.1 % 27 13
Test Date: 2026-11-12 04:47:19
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <optional>
       7              : #include <type_traits>
       8              : #include <utility>
       9              : 
      10              : #include "Utilities/Gsl.hpp"
      11              : 
      12              : /// An object or reference.
      13              : ///
      14              : /// This class can either store an object or point to a preexisting
      15              : /// one, giving uniform access to the two cases.
      16              : template <typename T>
      17            1 : class MaybeOwned {
      18              :  public:
      19            0 :   using value_type = T;
      20              : 
      21            0 :   MaybeOwned(MaybeOwned&&) = default;
      22            0 :   MaybeOwned& operator=(MaybeOwned&&) = default;
      23              : 
      24              :   // Not clear what correct semantics for copying a non-owning object
      25              :   // would be.
      26            0 :   MaybeOwned(const MaybeOwned&) = delete;
      27            0 :   MaybeOwned& operator=(const MaybeOwned&) = delete;
      28              : 
      29            0 :   ~MaybeOwned() = default;
      30              : 
      31              :   /// A default constructed MaybeOwned<T> owns a default-constructed T.
      32            1 :   MaybeOwned() : owned_value_(std::in_place) {}
      33              : 
      34              :   /// Create an owning object.
      35              :   // NOLINTNEXTLINE(google-explicit-constructor)
      36            1 :   MaybeOwned(std::remove_const_t<T> owned) : owned_value_(std::move(owned)) {}
      37              :   /// Create a non-owning object.
      38              :   // NOLINTNEXTLINE(google-explicit-constructor)
      39            1 :   MaybeOwned(const gsl::not_null<T*> unowned) : unowned_value_(unowned.get()) {}
      40              : 
      41              :   // The conversion sequence
      42              :   //   not_null<T*> -> not_null<const T*> -> MaybeOwned<const T>
      43              :   // is too complex to be found automatically.
      44              : 
      45              :   /// Create a non-owning object when the previous constructor needs
      46              :   /// too many implicit conversions.
      47              :   // NOLINTNEXTLINE(google-explicit-constructor)
      48            1 :   MaybeOwned(const gsl::not_null<std::remove_const_t<T>*> unowned)
      49              :     requires std::is_const_v<T>
      50              :       : MaybeOwned(gsl::not_null<T*>(unowned)) {}
      51              : 
      52              :   /// Conversion from MaybeOwned<T> to MaybeOwned<const T>
      53              :   // NOLINTNEXTLINE(google-explicit-constructor)
      54            1 :   MaybeOwned(MaybeOwned<std::remove_const_t<T>>&& other)
      55              :     requires std::is_const_v<T>
      56              :       : owned_value_(std::move(other).owned_value_),
      57              :         unowned_value_(other.unowned_value_) {}
      58              : 
      59              :   /// Conversion from MaybeOwned<T> to MaybeOwned<const T>
      60            1 :   MaybeOwned& operator=(MaybeOwned<std::remove_const_t<T>>&& other)
      61              :     requires std::is_const_v<T>
      62              :   {
      63              :     owned_value_ = std::move(other).owned_value_;
      64              :     unowned_value_ = other.unowned_value_;
      65              :     return *this;
      66              :   }
      67              : 
      68              :   /// Change the object to owning, destroying any previously owned value.
      69            1 :   MaybeOwned& operator=(std::remove_const_t<T> owned) {
      70              :     owned_value_.emplace(std::move(owned));
      71              :     unowned_value_ = nullptr;
      72              :     return *this;
      73              :   }
      74              :   /// Change the object to non-owning.
      75            1 :   MaybeOwned& operator=(const gsl::not_null<T*> unowned) {
      76              :     owned_value_.reset();
      77              :     unowned_value_ = unowned.get();
      78              :     return *this;
      79              :   }
      80              : 
      81              :   /// Access the contained or referenced object
      82              :   /// @{
      83            1 :   T& operator*() {
      84              :     return owned_value_.has_value() ? *owned_value_ : *unowned_value_;
      85              :   }
      86            1 :   const T& operator*() const {
      87              :     return owned_value_.has_value() ? *owned_value_ : *unowned_value_;
      88              :   }
      89              : 
      90            1 :   T* operator->() { return &**this; }
      91            1 :   const T* operator->() const { return &**this; }
      92              :   /// @}
      93              : 
      94            0 :   bool is_owning() const { return owned_value_.has_value(); }
      95              : 
      96              :   /// Get the owned object, or a copy if non-owning.
      97            0 :   std::remove_const_t<T> to_owned() && {
      98              :     if (owned_value_.has_value()) {
      99              :       return std::move(*owned_value_);
     100              :     } else {
     101              :       return *unowned_value_;
     102              :     }
     103              :   }
     104              : 
     105              :  private:
     106              :   friend class MaybeOwned<const T>;
     107              : 
     108            0 :   std::optional<std::remove_const_t<T>> owned_value_{};
     109            0 :   T* unowned_value_ = nullptr;
     110              : };
     111              : 
     112              : template <typename T>
     113            0 : MaybeOwned(T) -> MaybeOwned<T>;
     114              : 
     115              : // Storing a reference or pointer to a not_null seems unlikely enough
     116              : // that we assume the user wanted the other behavior.  The class can
     117              : // still be instantiated with an explicit argument if someone really
     118              : // wants that.
     119              : template <typename T>
     120            0 : MaybeOwned(gsl::not_null<T*>) -> MaybeOwned<T>;
     121              : 
     122              : // Disable pointers, as the user probably meant to use the not_null
     123              : // call, but not definitely enough that inferring seems like a good
     124              : // idea.
     125              : //
     126              : // "= delete" would be more appropriate, but the standards committee
     127              : // appears to have approved that and then just forgotten to add it to
     128              : // the standard or something.
     129              : template <typename T>
     130            0 : MaybeOwned(T*) -> MaybeOwned<void>;
        

Generated by: LCOV version 2.0-1