blob: ae4cd5f1d25dfea03536a6c2f06e736f784c5b19 [file] [log] [blame]
kwiberg84f6a3f2017-09-05 15:43:131/*
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
Mirko Bonadei92ea95e2017-09-15 04:47:3111#ifndef API_OPTIONAL_H_
12#define API_OPTIONAL_H_
kwiberg84f6a3f2017-09-05 15:43:1313
14#include <algorithm>
15#include <memory>
16#include <utility>
17
18#ifdef UNIT_TEST
19#include <iomanip>
20#include <ostream>
21#endif // UNIT_TEST
22
Mirko Bonadei92ea95e2017-09-15 04:47:3123#include "api/array_view.h"
24#include "rtc_base/checks.h"
25#include "rtc_base/sanitizer.h"
kwiberg84f6a3f2017-09-05 15:43:1326
27namespace rtc {
28
29namespace optional_internal {
30
31#if RTC_HAS_ASAN
32
33// This is a non-inlined function. The optimizer can't see inside it. It
34// prevents the compiler from generating optimized code that reads value_ even
35// if it is unset. Although safe, this causes memory sanitizers to complain.
36void* FunctionThatDoesNothingImpl(void*);
37
38template <typename T>
39inline T* FunctionThatDoesNothing(T* x) {
40 return reinterpret_cast<T*>(
41 FunctionThatDoesNothingImpl(reinterpret_cast<void*>(x)));
42}
43
44#else
45
46template <typename T>
47inline T* FunctionThatDoesNothing(T* x) {
48 return x;
49}
50
51#endif
52
53} // namespace optional_internal
54
55// Simple std::optional-wannabe. It either contains a T or not.
56//
57// A moved-from Optional<T> may only be destroyed, and assigned to if T allows
58// being assigned to after having been moved from. Specifically, you may not
59// assume that it just doesn't contain a value anymore.
60//
61// Examples of good places to use Optional:
62//
63// - As a class or struct member, when the member doesn't always have a value:
64// struct Prisoner {
65// std::string name;
66// Optional<int> cell_number; // Empty if not currently incarcerated.
67// };
68//
69// - As a return value for functions that may fail to return a value on all
70// allowed inputs. For example, a function that searches an array might
71// return an Optional<size_t> (the index where it found the element, or
72// nothing if it didn't find it); and a function that parses numbers might
73// return Optional<double> (the parsed number, or nothing if parsing failed).
74//
75// Examples of bad places to use Optional:
76//
77// - As a return value for functions that may fail because of disallowed
78// inputs. For example, a string length function should not return
79// Optional<size_t> so that it can return nothing in case the caller passed
80// it a null pointer; the function should probably use RTC_[D]CHECK instead,
81// and return plain size_t.
82//
83// - As a return value for functions that may fail to return a value on all
84// allowed inputs, but need to tell the caller what went wrong. Returning
85// Optional<double> when parsing a single number as in the example above
86// might make sense, but any larger parse job is probably going to need to
87// tell the caller what the problem was, not just that there was one.
88//
89// - As a non-mutable function argument. When you want to pass a value of a
90// type T that can fail to be there, const T* is almost always both fastest
91// and cleanest. (If you're *sure* that the the caller will always already
92// have an Optional<T>, const Optional<T>& is slightly faster than const T*,
93// but this is a micro-optimization. In general, stick to const T*.)
94//
95// TODO(kwiberg): Get rid of this class when the standard library has
96// std::optional (and we're allowed to use it).
97template <typename T>
98class Optional final {
99 public:
100 // Construct an empty Optional.
101 Optional() : has_value_(false), empty_('\0') { PoisonValue(); }
102
103 // Construct an Optional that contains a value.
104 explicit Optional(const T& value) : has_value_(true) {
105 new (&value_) T(value);
106 }
107 explicit Optional(T&& value) : has_value_(true) {
108 new (&value_) T(std::move(value));
109 }
110
111 // Copy constructor: copies the value from m if it has one.
112 Optional(const Optional& m) : has_value_(m.has_value_) {
113 if (has_value_)
114 new (&value_) T(m.value_);
115 else
116 PoisonValue();
117 }
118
119 // Move constructor: if m has a value, moves the value from m, leaving m
120 // still in a state where it has a value, but a moved-from one (the
121 // properties of which depends on T; the only general guarantee is that we
122 // can destroy m).
123 Optional(Optional&& m) : has_value_(m.has_value_) {
124 if (has_value_)
125 new (&value_) T(std::move(m.value_));
126 else
127 PoisonValue();
128 }
129
130 ~Optional() {
131 if (has_value_)
132 value_.~T();
133 else
134 UnpoisonValue();
135 }
136
137 // Copy assignment. Uses T's copy assignment if both sides have a value, T's
138 // copy constructor if only the right-hand side has a value.
139 Optional& operator=(const Optional& m) {
140 if (m.has_value_) {
141 if (has_value_) {
142 value_ = m.value_; // T's copy assignment.
143 } else {
144 UnpoisonValue();
145 new (&value_) T(m.value_); // T's copy constructor.
146 has_value_ = true;
147 }
148 } else {
149 reset();
150 }
151 return *this;
152 }
153
154 // Move assignment. Uses T's move assignment if both sides have a value, T's
155 // move constructor if only the right-hand side has a value. The state of m
156 // after it's been moved from is as for the move constructor.
157 Optional& operator=(Optional&& m) {
158 if (m.has_value_) {
159 if (has_value_) {
160 value_ = std::move(m.value_); // T's move assignment.
161 } else {
162 UnpoisonValue();
163 new (&value_) T(std::move(m.value_)); // T's move constructor.
164 has_value_ = true;
165 }
166 } else {
167 reset();
168 }
169 return *this;
170 }
171
172 // Swap the values if both m1 and m2 have values; move the value if only one
173 // of them has one.
174 friend void swap(Optional& m1, Optional& m2) {
175 if (m1.has_value_) {
176 if (m2.has_value_) {
177 // Both have values: swap.
178 using std::swap;
179 swap(m1.value_, m2.value_);
180 } else {
181 // Only m1 has a value: move it to m2.
182 m2.UnpoisonValue();
183 new (&m2.value_) T(std::move(m1.value_));
184 m1.value_.~T(); // Destroy the moved-from value.
185 m1.has_value_ = false;
186 m2.has_value_ = true;
187 m1.PoisonValue();
188 }
189 } else if (m2.has_value_) {
190 // Only m2 has a value: move it to m1.
191 m1.UnpoisonValue();
192 new (&m1.value_) T(std::move(m2.value_));
193 m2.value_.~T(); // Destroy the moved-from value.
194 m1.has_value_ = true;
195 m2.has_value_ = false;
196 m2.PoisonValue();
197 }
198 }
199
200 // Destroy any contained value. Has no effect if we have no value.
201 void reset() {
202 if (!has_value_)
203 return;
204 value_.~T();
205 has_value_ = false;
206 PoisonValue();
207 }
208
209 template <class... Args>
210 void emplace(Args&&... args) {
211 if (has_value_)
212 value_.~T();
213 else
214 UnpoisonValue();
215 new (&value_) T(std::forward<Args>(args)...);
216 has_value_ = true;
217 }
218
219 // Conversion to bool to test if we have a value.
220 explicit operator bool() const { return has_value_; }
221 bool has_value() const { return has_value_; }
222
223 // Dereferencing. Only allowed if we have a value.
224 const T* operator->() const {
225 RTC_DCHECK(has_value_);
226 return &value_;
227 }
228 T* operator->() {
229 RTC_DCHECK(has_value_);
230 return &value_;
231 }
232 const T& operator*() const {
233 RTC_DCHECK(has_value_);
234 return value_;
235 }
236 T& operator*() {
237 RTC_DCHECK(has_value_);
238 return value_;
239 }
240 const T& value() const {
241 RTC_DCHECK(has_value_);
242 return value_;
243 }
244 T& value() {
245 RTC_DCHECK(has_value_);
246 return value_;
247 }
248
249 // Dereference with a default value in case we don't have a value.
250 const T& value_or(const T& default_val) const {
251 // The no-op call prevents the compiler from generating optimized code that
252 // reads value_ even if !has_value_, but only if FunctionThatDoesNothing is
253 // not completely inlined; see its declaration.).
254 return has_value_ ? *optional_internal::FunctionThatDoesNothing(&value_)
255 : default_val;
256 }
257
258 // Dereference and move value.
259 T MoveValue() {
260 RTC_DCHECK(has_value_);
261 return std::move(value_);
262 }
263
264 // Equality tests. Two Optionals are equal if they contain equivalent values,
265 // or if they're both empty.
266 friend bool operator==(const Optional& m1, const Optional& m2) {
267 return m1.has_value_ && m2.has_value_ ? m1.value_ == m2.value_
268 : m1.has_value_ == m2.has_value_;
269 }
270 friend bool operator==(const Optional& opt, const T& value) {
271 return opt.has_value_ && opt.value_ == value;
272 }
273 friend bool operator==(const T& value, const Optional& opt) {
274 return opt.has_value_ && value == opt.value_;
275 }
276
277 friend bool operator!=(const Optional& m1, const Optional& m2) {
278 return m1.has_value_ && m2.has_value_ ? m1.value_ != m2.value_
279 : m1.has_value_ != m2.has_value_;
280 }
281 friend bool operator!=(const Optional& opt, const T& value) {
282 return !opt.has_value_ || opt.value_ != value;
283 }
284 friend bool operator!=(const T& value, const Optional& opt) {
285 return !opt.has_value_ || value != opt.value_;
286 }
287
288 private:
289 // Tell sanitizers that value_ shouldn't be touched.
290 void PoisonValue() {
291 rtc::AsanPoison(rtc::MakeArrayView(&value_, 1));
292 rtc::MsanMarkUninitialized(rtc::MakeArrayView(&value_, 1));
293 }
294
295 // Tell sanitizers that value_ is OK to touch again.
296 void UnpoisonValue() { rtc::AsanUnpoison(rtc::MakeArrayView(&value_, 1)); }
297
298 bool has_value_; // True iff value_ contains a live value.
299 union {
300 // empty_ exists only to make it possible to initialize the union, even when
301 // it doesn't contain any data. If the union goes uninitialized, it may
302 // trigger compiler warnings.
303 char empty_;
304 // By placing value_ in a union, we get to manage its construction and
305 // destruction manually: the Optional constructors won't automatically
306 // construct it, and the Optional destructor won't automatically destroy
307 // it. Basically, this just allocates a properly sized and aligned block of
308 // memory in which we can manually put a T with placement new.
309 T value_;
310 };
311};
312
313#ifdef UNIT_TEST
314namespace optional_internal {
315
316// Checks if there's a valid PrintTo(const T&, std::ostream*) call for T.
317template <typename T>
318struct HasPrintTo {
319 private:
320 struct No {};
321
322 template <typename T2>
323 static auto Test(const T2& obj)
324 -> decltype(PrintTo(obj, std::declval<std::ostream*>()));
325
326 template <typename>
327 static No Test(...);
328
329 public:
330 static constexpr bool value =
331 !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
332};
333
334// Checks if there's a valid operator<<(std::ostream&, const T&) call for T.
335template <typename T>
336struct HasOstreamOperator {
337 private:
338 struct No {};
339
340 template <typename T2>
341 static auto Test(const T2& obj)
342 -> decltype(std::declval<std::ostream&>() << obj);
343
344 template <typename>
345 static No Test(...);
346
347 public:
348 static constexpr bool value =
349 !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
350};
351
352// Prefer using PrintTo to print the object.
353template <typename T>
354typename std::enable_if<HasPrintTo<T>::value, void>::type OptionalPrintToHelper(
355 const T& value,
356 std::ostream* os) {
357 PrintTo(value, os);
358}
359
360// Fall back to operator<<(std::ostream&, ...) if it exists.
361template <typename T>
362typename std::enable_if<HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
363 void>::type
364OptionalPrintToHelper(const T& value, std::ostream* os) {
365 *os << value;
366}
367
368inline void OptionalPrintObjectBytes(const unsigned char* bytes,
369 size_t size,
370 std::ostream* os) {
371 *os << "<optional with " << size << "-byte object [";
372 for (size_t i = 0; i != size; ++i) {
373 *os << (i == 0 ? "" : ((i & 1) ? "-" : " "));
374 *os << std::hex << std::setw(2) << std::setfill('0')
375 << static_cast<int>(bytes[i]);
376 }
377 *os << "]>";
378}
379
380// As a final back-up, just print the contents of the objcets byte-wise.
381template <typename T>
382typename std::enable_if<!HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
383 void>::type
384OptionalPrintToHelper(const T& value, std::ostream* os) {
385 OptionalPrintObjectBytes(reinterpret_cast<const unsigned char*>(&value),
386 sizeof(value), os);
387}
388
389} // namespace optional_internal
390
391// PrintTo is used by gtest to print out the results of tests. We want to ensure
392// the object contained in an Optional can be printed out if it's set, while
393// avoiding touching the object's storage if it is undefined.
394template <typename T>
395void PrintTo(const rtc::Optional<T>& opt, std::ostream* os) {
396 if (opt) {
397 optional_internal::OptionalPrintToHelper(*opt, os);
398 } else {
399 *os << "<empty optional>";
400 }
401}
402
403#endif // UNIT_TEST
404
405} // namespace rtc
406
Mirko Bonadei92ea95e2017-09-15 04:47:31407#endif // API_OPTIONAL_H_