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