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. Optional()65 Optional() : has_value_(false) {} 66 67 // Construct an Optional that contains a value. Optional(const T & val)68 explicit Optional(const T& val) : value_(val), has_value_(true) {} Optional(T && val)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; Optional(Optional && m)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 swap(Optional & m1,Optional & m2)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. value_or(const T & default_val)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