Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2015 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #ifndef WEBRTC_BASE_OPTIONAL_H_
     12 #define WEBRTC_BASE_OPTIONAL_H_
     13 
     14 #include <algorithm>
     15 #include <utility>
     16 
     17 #include "webrtc/base/checks.h"
     18 
     19 namespace rtc {
     20 
     21 // Simple std::experimental::optional-wannabe. It either contains a T or not.
     22 // In order to keep the implementation simple and portable, this implementation
     23 // actually contains a (default-constructed) T even when it supposedly doesn't
     24 // contain a value; use e.g. rtc::scoped_ptr<T> instead if that's too
     25 // expensive.
     26 //
     27 // A moved-from Optional<T> may only be destroyed, and assigned to if T allows
     28 // being assigned to after having been moved from. Specifically, you may not
     29 // assume that it just doesn't contain a value anymore.
     30 //
     31 // Examples of good places to use Optional:
     32 //
     33 // - As a class or struct member, when the member doesn't always have a value:
     34 //     struct Prisoner {
     35 //       std::string name;
     36 //       Optional<int> cell_number;  // Empty if not currently incarcerated.
     37 //     };
     38 //
     39 // - As a return value for functions that may fail to return a value on all
     40 //   allowed inputs. For example, a function that searches an array might
     41 //   return an Optional<size_t> (the index where it found the element, or
     42 //   nothing if it didn't find it); and a function that parses numbers might
     43 //   return Optional<double> (the parsed number, or nothing if parsing failed).
     44 //
     45 // Examples of bad places to use Optional:
     46 //
     47 // - As a return value for functions that may fail because of disallowed
     48 //   inputs. For example, a string length function should not return
     49 //   Optional<size_t> so that it can return nothing in case the caller passed
     50 //   it a null pointer; the function should probably use RTC_[D]CHECK instead,
     51 //   and return plain size_t.
     52 //
     53 // - As a return value for functions that may fail to return a value on all
     54 //   allowed inputs, but need to tell the caller what went wrong. Returning
     55 //   Optional<double> when parsing a single number as in the example above
     56 //   might make sense, but any larger parse job is probably going to need to
     57 //   tell the caller what the problem was, not just that there was one.
     58 //
     59 // TODO(kwiberg): Get rid of this class when the standard library has
     60 // std::optional (and we're allowed to use it).
     61 template <typename T>
     62 class Optional final {
     63  public:
     64   // Construct an empty Optional.
     65   Optional() : has_value_(false) {}
     66 
     67   // Construct an Optional that contains a value.
     68   explicit Optional(const T& val) : value_(val), has_value_(true) {}
     69   explicit Optional(T&& val) : value_(std::move(val)), has_value_(true) {}
     70 
     71   // Copy and move constructors.
     72   // TODO(kwiberg): =default the move constructor when MSVC supports it.
     73   Optional(const Optional&) = default;
     74   Optional(Optional&& m)
     75       : value_(std::move(m.value_)), has_value_(m.has_value_) {}
     76 
     77   // Assignment.
     78   // TODO(kwiberg): =default the move assignment op when MSVC supports it.
     79   Optional& operator=(const Optional&) = default;
     80   Optional& operator=(Optional&& m) {
     81     value_ = std::move(m.value_);
     82     has_value_ = m.has_value_;
     83     return *this;
     84   }
     85 
     86   friend void swap(Optional& m1, Optional& m2) {
     87     using std::swap;
     88     swap(m1.value_, m2.value_);
     89     swap(m1.has_value_, m2.has_value_);
     90   }
     91 
     92   // Conversion to bool to test if we have a value.
     93   explicit operator bool() const { return has_value_; }
     94 
     95   // Dereferencing. Only allowed if we have a value.
     96   const T* operator->() const {
     97     RTC_DCHECK(has_value_);
     98     return &value_;
     99   }
    100   T* operator->() {
    101     RTC_DCHECK(has_value_);
    102     return &value_;
    103   }
    104   const T& operator*() const {
    105     RTC_DCHECK(has_value_);
    106     return value_;
    107   }
    108   T& operator*() {
    109     RTC_DCHECK(has_value_);
    110     return value_;
    111   }
    112 
    113   // Dereference with a default value in case we don't have a value.
    114   const T& value_or(const T& default_val) const {
    115     return has_value_ ? value_ : default_val;
    116   }
    117 
    118   // Equality tests. Two Optionals are equal if they contain equivalent values,
    119   // or
    120   // if they're both empty.
    121   friend bool operator==(const Optional& m1, const Optional& m2) {
    122     return m1.has_value_ && m2.has_value_ ? m1.value_ == m2.value_
    123                                           : m1.has_value_ == m2.has_value_;
    124   }
    125   friend bool operator!=(const Optional& m1, const Optional& m2) {
    126     return m1.has_value_ && m2.has_value_ ? m1.value_ != m2.value_
    127                                           : m1.has_value_ != m2.has_value_;
    128   }
    129 
    130  private:
    131   // Invariant: Unless *this has been moved from, value_ is default-initialized
    132   // (or copied or moved from a default-initialized T) if !has_value_.
    133   T value_;
    134   bool has_value_;
    135 };
    136 
    137 }  // namespace rtc
    138 
    139 #endif  // WEBRTC_BASE_OPTIONAL_H_
    140