LCOV - code coverage report
Current view: top level - datadog - expected.h (source / functions) Hit Total Coverage
Test: filtered.info Lines: 40 40 100.0 %
Date: 2024-01-03 20:30:12 Functions: 157 160 98.1 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : // This component provides a class template, `Expected<T>`, that is either an
       4             : // instance of `T` or an instance of `Error`.  `Expected<void>` is either
       5             : // `nullopt` or an instance of `Error`.
       6             : //
       7             : // `Expected` is inspired by, but incompatible with, C++23's `std::expected`.
       8             : //
       9             : // Example Usage
      10             : // -------------
      11             : // The following excerpt demonstrates the intended usage of `Expected<T>`:
      12             : //
      13             : //     Expected<int> parse_integer(StringView name);
      14             : //
      15             : //
      16             : //     int main() {
      17             : //       auto maybe_int = parse_integer("the answer");
      18             : //       // using the `if_error` method
      19             : //       if (auto *error = maybe_int.if_error()) {
      20             : //         std::cerr << "parse_integer returned error: " << *error << '\n';
      21             : //         return int(error->code);
      22             : //       }
      23             : //
      24             : //       assert(*maybe_int == 42);
      25             : //
      26             : //       maybe_int = parse_integer("one hundred twenty-three");
      27             : //       // use the `error` method.
      28             : //       if (!maybe_int) {
      29             : //         std::cerr << "parse_integer returned error: " << maybe_int.error() <<
      30             : //         '\n'; return int(maybe_int.error().code);
      31             : //       }
      32             : //
      33             : //       assert(maybe_int == 123);
      34             : //     }
      35             : //
      36             : // `Expected<void>` is like `Expected<T>`, except that if the value is not an
      37             : // error then it cannot be "dereferenced" with `operator*`, i.e. it is analogous
      38             : // to `Optional<Error>` (and is implemented as such).
      39             : 
      40             : #include <variant>
      41             : 
      42             : #include "error.h"
      43             : #include "optional.h"
      44             : 
      45             : namespace datadog {
      46             : namespace tracing {
      47             : 
      48             : template <typename Value>
      49             : class Expected {
      50             :   std::variant<Value, Error> data_;
      51             : 
      52             :  public:
      53             :   Expected() = default;
      54             :   Expected(const Expected&) = default;
      55             :   Expected(Expected&) = default;
      56         142 :   Expected(Expected&&) = default;
      57             :   Expected& operator=(const Expected&) = default;
      58          63 :   Expected& operator=(Expected&&) = default;
      59             : 
      60             :   template <typename Other>
      61             :   Expected(Other&&);
      62             :   template <typename Other>
      63             :   Expected& operator=(Other&&);
      64             : 
      65             :   // Return whether this object holds a `Value` (as opposed to an `Error`).
      66             :   bool has_value() const noexcept;
      67             :   explicit operator bool() const noexcept;
      68             : 
      69             :   // Return a reference to the `Value` held by this object.  If this object is
      70             :   // an `Error`, throw a `std::bad_variant_access`.
      71             :   Value& value() &;
      72             :   const Value& value() const&;
      73             :   Value&& value() &&;
      74             :   const Value&& value() const&&;
      75             :   Value& operator*() &;
      76             :   const Value& operator*() const&;
      77             :   Value&& operator*() &&;
      78             :   const Value&& operator*() const&&;
      79             : 
      80             :   // Return a pointer to the `Value` held by this object.  If this object is an
      81             :   // `Error`, throw a `std::bad_variant_access`.
      82             :   Value* operator->();
      83             :   const Value* operator->() const;
      84             : 
      85             :   // Return a reference to the `Error` held by this object.  If this object is
      86             :   // not an `Error`, throw a `std::bad_variant_access`.
      87             :   Error& error() &;
      88             :   const Error& error() const&;
      89             :   Error&& error() &&;
      90             :   const Error&& error() const&&;
      91             : 
      92             :   // Return a pointer to the `Error` value held by this object, or return
      93             :   // `nullptr` if this object is not an `Error`.
      94             :   Error* if_error() &;
      95             :   const Error* if_error() const&;
      96             :   // Don't use `if_error` on an rvalue (temporary).
      97             :   Error* if_error() && = delete;
      98             :   const Error* if_error() const&& = delete;
      99             : };
     100             : 
     101             : template <typename Value>
     102             : template <typename Other>
     103       31323 : Expected<Value>::Expected(Other&& other) : data_(std::forward<Other>(other)) {}
     104             : 
     105             : template <typename Value>
     106             : template <typename Other>
     107             : Expected<Value>& Expected<Value>::operator=(Other&& other) {
     108             :   data_ = std::forward<Other>(other);
     109             :   return *this;
     110             : }
     111             : 
     112             : template <typename Value>
     113        2546 : bool Expected<Value>::has_value() const noexcept {
     114        2546 :   return std::holds_alternative<Value>(data_);
     115             : }
     116             : template <typename Value>
     117        2546 : Expected<Value>::operator bool() const noexcept {
     118        2546 :   return has_value();
     119             : }
     120             : 
     121             : template <typename Value>
     122       30857 : Value& Expected<Value>::value() & {
     123       30857 :   return std::get<0>(data_);
     124             : }
     125             : template <typename Value>
     126         211 : const Value& Expected<Value>::value() const& {
     127         211 :   return std::get<0>(data_);
     128             : }
     129             : template <typename Value>
     130             : Value&& Expected<Value>::value() && {
     131             :   return std::move(std::get<0>(data_));
     132             : }
     133             : template <typename Value>
     134             : const Value&& Expected<Value>::value() const&& {
     135             :   return std::move(std::get<0>(data_));
     136             : }
     137             : 
     138             : template <typename Value>
     139        4215 : Value& Expected<Value>::operator*() & {
     140        4215 :   return value();
     141             : }
     142             : template <typename Value>
     143          74 : const Value& Expected<Value>::operator*() const& {
     144          74 :   return value();
     145             : }
     146             : template <typename Value>
     147       26529 : Value&& Expected<Value>::operator*() && {
     148       26529 :   return std::move(value());
     149             : }
     150             : template <typename Value>
     151             : const Value&& Expected<Value>::operator*() const&& {
     152             :   return std::move(value());
     153             : }
     154             : 
     155             : template <typename Value>
     156         113 : Value* Expected<Value>::operator->() {
     157         113 :   return &value();
     158             : }
     159             : template <typename Value>
     160         137 : const Value* Expected<Value>::operator->() const {
     161         137 :   return &value();
     162             : }
     163             : 
     164             : template <typename Value>
     165         187 : Error& Expected<Value>::error() & {
     166         187 :   return std::get<1>(data_);
     167             : }
     168             : template <typename Value>
     169          48 : const Error& Expected<Value>::error() const& {
     170          48 :   return std::get<1>(data_);
     171             : }
     172             : template <typename Value>
     173             : Error&& Expected<Value>::error() && {
     174             :   return std::move(std::get<1>(data_));
     175             : }
     176             : template <typename Value>
     177             : const Error&& Expected<Value>::error() const&& {
     178             :   return std::move(std::get<1>(data_));
     179             : }
     180             : 
     181             : template <typename Value>
     182        2385 : Error* Expected<Value>::if_error() & {
     183        2385 :   return std::get_if<1>(&data_);
     184             : }
     185             : template <typename Value>
     186             : const Error* Expected<Value>::if_error() const& {
     187             :   return std::get_if<1>(&data_);
     188             : }
     189             : 
     190             : template <>
     191             : class Expected<void> {
     192             :   Optional<Error> data_;
     193             : 
     194             :  public:
     195      130740 :   Expected() = default;
     196             :   Expected(const Expected&) = default;
     197             :   Expected(Expected&) = default;
     198             :   Expected(Expected&&) = default;
     199             :   Expected& operator=(const Expected&) = default;
     200       23439 :   Expected& operator=(Expected&&) = default;
     201             : 
     202             :   template <typename Other>
     203             :   Expected(Other&&);
     204             :   template <typename Other>
     205             :   Expected& operator=(Other&&);
     206             : 
     207             :   void swap(Expected& other);
     208             : 
     209             :   bool has_value() const;
     210             :   explicit operator bool() const;
     211             : 
     212             :   Error& error() &;
     213             :   const Error& error() const&;
     214             :   Error&& error() &&;
     215             :   const Error&& error() const&&;
     216             : 
     217             :   Error* if_error() &;
     218             :   const Error* if_error() const&;
     219             :   // Don't use `if_error` on an rvalue (temporary).
     220             :   Error* if_error() && = delete;
     221             :   const Error* if_error() const&& = delete;
     222             : };
     223             : 
     224             : template <typename Other>
     225       11367 : Expected<void>::Expected(Other&& other) : data_(std::forward<Other>(other)) {}
     226             : 
     227             : template <typename Other>
     228           4 : Expected<void>& Expected<void>::operator=(Other&& other) {
     229           4 :   data_ = std::forward<Other>(other);
     230           4 :   return *this;
     231             : }
     232             : 
     233             : inline void Expected<void>::swap(Expected& other) { data_.swap(other.data_); }
     234             : 
     235       19160 : inline bool Expected<void>::has_value() const { return !data_.has_value(); }
     236       19160 : inline Expected<void>::operator bool() const { return has_value(); }
     237             : 
     238           8 : inline Error& Expected<void>::error() & { return *data_; }
     239          23 : inline const Error& Expected<void>::error() const& { return *data_; }
     240             : inline Error&& Expected<void>::error() && { return std::move(*data_); }
     241             : inline const Error&& Expected<void>::error() const&& {
     242             :   return std::move(*data_);
     243             : }
     244             : 
     245       10914 : inline Error* Expected<void>::if_error() & { return data_ ? &*data_ : nullptr; }
     246       82875 : inline const Error* Expected<void>::if_error() const& {
     247       82875 :   return data_ ? &*data_ : nullptr;
     248             : }
     249             : 
     250             : }  // namespace tracing
     251             : }  // namespace datadog

Generated by: LCOV version 1.16