SpECTRE Documentation Coverage Report
Current view: top level - Utilities - Expected.hpp Coverage Total Hit
Commit: a37d7b3c1803b88b537d2aef1c27ca5e6b499398 Lines: 35.3 % 17 6
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 <ostream>
       7              : #include <utility>
       8              : 
       9              : #include "Utilities/ErrorHandling/Error.hpp"
      10              : #include "Utilities/Kokkos/KokkosMacros.hpp"
      11              : 
      12              : /*!
      13              :  * \ingroup UtilitiesGroup
      14              :  * \brief Wraps an error to construct an `Expected` that holds the error.
      15              :  */
      16              : template <typename E>
      17            1 : struct Unexpected {
      18            0 :   E error;
      19              : };
      20              : 
      21              : template <typename E>
      22            0 : Unexpected(E) -> Unexpected<E>;
      23              : 
      24              : namespace Expected_detail {
      25              : template <typename E>
      26              : concept streamable =
      27              :     requires(std::ostream& os, const E& error) { os << error; };
      28              : }  // namespace Expected_detail
      29              : 
      30              : /*!
      31              :  * \ingroup UtilitiesGroup
      32              :  * \brief Holds either a value of type `T` or an error of type `E`, like a
      33              :  * minimal version of C++23's `std::expected`.
      34              :  *
      35              :  * Construct an `Expected` from a `T` to hold a value, or from an
      36              :  * `Unexpected<E>` to hold an error. Return an `Expected` from functions that
      37              :  * can fail to let the caller decide how to handle the failure.
      38              :  *
      39              :  * \snippet Test_Expected.cpp expected_example
      40              :  *
      41              :  * Calling `value()` when there is an error, or `error()` when there is a
      42              :  * value, is an error (also in release builds).
      43              :  *
      44              :  * Unlike `std::expected`, this class stores both a `T` and an `E`, so both must
      45              :  * be default-constructible and the one that isn't held is default-constructed.
      46              :  * This keeps the class simple.
      47              :  */
      48              : template <typename T, typename E>
      49            1 : class Expected {
      50              :  public:
      51              :   // NOLINTNEXTLINE(google-explicit-constructor): converts like std::expected
      52            0 :   constexpr Expected(T value) : value_(std::move(value)), has_value_(true) {}
      53              :   // NOLINTNEXTLINE(google-explicit-constructor): converts like std::expected
      54            0 :   constexpr Expected(Unexpected<E> unexpected)
      55              :       : error_(std::move(unexpected.error)), has_value_(false) {}
      56              : 
      57            0 :   constexpr bool has_value() const { return has_value_; }
      58            0 :   constexpr explicit operator bool() const { return has_value_; }
      59              : 
      60              :   /// @{
      61              :   /// The value. It is an error to call this if `has_value()` is false.
      62            1 :   constexpr const T& value() const& {
      63              :     check_has_value();
      64              :     return value_;
      65              :   }
      66            1 :   constexpr T& value() & {
      67              :     check_has_value();
      68              :     return value_;
      69              :   }
      70            1 :   constexpr T&& value() && {
      71              :     check_has_value();
      72              :     return std::move(value_);
      73              :   }
      74              :   /// @}
      75              : 
      76              :   /// The error. It is an error to call this if `has_value()` is true.
      77            1 :   constexpr const E& error() const {
      78              :     if (has_value_) {
      79              :       KOKKOS_IF_ON_HOST((ERROR("Expected holds a value, not an error.");))
      80              :       KOKKOS_IF_ON_DEVICE(
      81              :           (Kokkos::abort("Expected holds a value, not an error.");))
      82              :     }
      83              :     return error_;
      84              :   }
      85              : 
      86              :  private:
      87            0 :   constexpr void check_has_value() const {
      88              :     if (not has_value_) {
      89              :       KOKKOS_IF_ON_HOST((
      90              :           if constexpr (Expected_detail::streamable<E>) {
      91              :             ERROR("Expected holds an error, not a value. The error is:\n"
      92              :                   << error_);
      93              :           } else { ERROR("Expected holds an error, not a value."); }))
      94              :       KOKKOS_IF_ON_DEVICE(
      95              :           (Kokkos::abort("Expected holds an error, not a value.");))
      96              :     }
      97              :   }
      98              : 
      99            0 :   T value_{};
     100            0 :   E error_{};
     101            0 :   bool has_value_;
     102              : };
        

Generated by: LCOV version 2.0-1