LCOV - code coverage report
Current view: top level - envoy/common - optref.h (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 19 31 61.3 %
Date: 2024-01-05 06:35:25 Functions: 217 625 34.7 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "absl/types/optional.h" // required for absl::nullopt
       4             : 
       5             : namespace Envoy {
       6             : 
       7             : // Helper class to make it easier to work with optional references, allowing:
       8             : //   foo(OptRef<T> t) {
       9             : //     if (t.has_value()) {
      10             : //       t->method();
      11             : //     }
      12             : //   }
      13             : //
      14             : // Using absl::optional directly you must write optref.value().method() which is
      15             : // a bit more awkward.
      16             : //
      17             : // This class also consumes less memory -- e.g. 8 bytes for a pointer rather
      18             : // than 16 bytes for a pointer plus a bool with alignment padding.
      19             : template <class T> struct OptRef {
      20       26096 :   OptRef(T& t) : ptr_(&t) {}
      21       23981 :   OptRef() : ptr_(nullptr) {}
      22        5485 :   OptRef(absl::nullopt_t) : ptr_(nullptr) {}
      23             : 
      24             :   /**
      25             :    * Copy constructor that allows conversion.
      26             :    */
      27        1579 :   template <class From> explicit OptRef(OptRef<From> rhs) : ptr_(rhs.ptr()) {}
      28             : 
      29             :   /**
      30             :    * Assignment that allows conversion.
      31             :    */
      32             :   template <class From> OptRef<T>& operator=(OptRef<From> rhs) {
      33             :     ptr_ = rhs.ptr();
      34             :     return *this;
      35             :   }
      36             : 
      37             :   /**
      38             :    * Helper to call a const method on T. The caller is responsible for ensuring
      39             :    * has_value() is true.
      40             :    */
      41       15404 :   T* operator->() const { return ptr_; }
      42             : 
      43             :   /**
      44             :    * Helper to convert a OptRef into a pointer. If the optional is not set, returns a nullptr.
      45             :    */
      46        4966 :   T* ptr() const { return ptr_; }
      47             : 
      48             :   /**
      49             :    * Helper to convert a OptRef into a ref. Behavior if !has_value() is undefined.
      50             :    */
      51        1466 :   T& ref() const { return *ptr_; } // NOLINT(clang-analyzer-core.uninitialized.UndefReturn)
      52             : 
      53             :   /**
      54             :    * Helper to dereference an OptRef. Behavior if !has_value() is undefined.
      55             :    */
      56        2990 :   T& operator*() const { return *ptr_; } // NOLINT(clang-analyzer-core.uninitialized.UndefReturn)
      57             : 
      58             :   /**
      59             :    * @return true if the object has a value.
      60             :    */
      61       39163 :   bool has_value() const { return ptr_ != nullptr; }
      62             : 
      63             :   /**
      64             :    * @return true if the object has a value.
      65             :    */
      66         714 :   bool operator!() const { return ptr_ == nullptr; }
      67        7684 :   operator bool() const { return ptr_ != nullptr; }
      68             : 
      69             :   /**
      70             :    * Copies the OptRef into an optional<T>. To use this, T must supply
      71             :    * an assignment operator.
      72             :    *
      73             :    * It is OK to copy an unset object -- it will result in an optional where
      74             :    * has_value() is false.
      75             :    *
      76             :    * @return an optional copy of the referenced object (or nullopt).
      77             :    */
      78           0 :   absl::optional<T> copy() const {
      79           0 :     absl::optional<T> ret;
      80           0 :     if (has_value()) {
      81           0 :       ret = *ptr_;
      82           0 :     }
      83           0 :     return ret;
      84           0 :   }
      85             : 
      86             :   /**
      87             :    * Places a reference to the an object into the OptRef.
      88             :    *
      89             :    * @param ref the object to be referenced.
      90             :    */
      91           0 :   void emplace(T& ref) { ptr_ = &ref; }
      92             : 
      93             :   /**
      94             :    * The value method has no intrinsic value to OptRef, but is left here for
      95             :    * compatibility reasons. This is used in call-sites which would be needed if
      96             :    * they were using optional<reference_wrapper<T>> directly without
      97             :    * OptRef. Having this function makes it easier upgrade to using OptRef
      98             :    * without having to change all call-sites.
      99             :    *
     100             :    * This must be called with has_value() true.
     101             :    *
     102             :    * @return a reference_wrapper around the value.
     103             :    */
     104             :   std::reference_wrapper<const T> value() const { return std::reference_wrapper<T>(*ptr_); }
     105        5010 :   std::reference_wrapper<T> value() { return std::reference_wrapper<T>(*ptr_); }
     106             : 
     107             :   /**
     108             :    * Clears any current reference.
     109             :    */
     110           0 :   void reset() { ptr_ = nullptr; }
     111             : 
     112             : private:
     113             :   T* ptr_;
     114             : };
     115             : 
     116             : /**
     117             :  * Constructs an OptRef<T> from the provided reference.
     118             :  * @param ref the reference to wrap
     119             :  * @return OptRef<T> the wrapped reference
     120             :  */
     121         475 : template <class T> OptRef<T> makeOptRef(T& ref) { return {ref}; }
     122             : 
     123             : /**
     124             :  * Constructs an OptRef<T> from the provided pointer.
     125             :  * @param ptr the pointer to wrap
     126             :  * @return OptRef<T> the wrapped pointer, or absl::nullopt if the pointer is nullptr
     127             :  */
     128       20390 : template <class T> OptRef<T> makeOptRefFromPtr(T* ptr) {
     129       20390 :   if (ptr == nullptr) {
     130       12919 :     return {};
     131       12919 :   }
     132             : 
     133        7471 :   return {*ptr};
     134       20390 : }
     135             : 
     136             : // Overloads for comparing OptRef against absl::nullopt.
     137           0 : template <class T> bool operator!=(const OptRef<T>& optref, absl::nullopt_t) {
     138           0 :   return optref.has_value();
     139           0 : }
     140             : template <class T> bool operator!=(absl::nullopt_t, const OptRef<T>& optref) {
     141             :   return optref.has_value();
     142             : }
     143             : template <class T> bool operator==(const OptRef<T>& optref, absl::nullopt_t) {
     144             :   return !optref.has_value();
     145             : }
     146             : template <class T> bool operator==(absl::nullopt_t, const OptRef<T>& optref) {
     147             :   return !optref.has_value();
     148             : }
     149             : 
     150             : } // namespace Envoy

Generated by: LCOV version 1.15