1 //  Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 
6 #pragma once
7 
8 /*
9  * Optional - For conditional initialization of values, like boost::optional,
10  * but with support for move semantics and emplacement.  Reference type support
11  * has not been included due to limited use cases and potential confusion with
12  * semantics of assignment: Assigning to an optional reference could quite
13  * reasonably copy its value or redirect the reference.
14  *
15  * Optional can be useful when a variable might or might not be needed:
16  *
17  *  Optional<Logger> maybeLogger = ...;
18  *  if (maybeLogger) {
19  *    maybeLogger->log("hello");
20  *  }
21  *
22  * Optional enables a 'null' value for types which do not otherwise have
23  * nullability, especially useful for parameter passing:
24  *
25  * void testIterator(const unique_ptr<Iterator>& it,
26  *                   initializer_list<int> idsExpected,
27  *                   Optional<initializer_list<int>> ranksExpected = none) {
28  *   for (int i = 0; it->next(); ++i) {
29  *     EXPECT_EQ(it->doc().id(), idsExpected[i]);
30  *     if (ranksExpected) {
31  *       EXPECT_EQ(it->doc().rank(), (*ranksExpected)[i]);
32  *     }
33  *   }
34  * }
35  *
36  * Optional models OptionalPointee, so calling 'get_pointer(opt)' will return a
37  * pointer to nullptr if the 'opt' is empty, and a pointer to the value if it is
38  * not:
39  *
40  *  Optional<int> maybeInt = ...;
41  *  if (int* v = get_pointer(maybeInt)) {
42  *    cout << *v << endl;
43  *  }
44  */
45 
46 #include <cstddef>
47 #include <functional>
48 #include <new>
49 #include <stdexcept>
50 #include <type_traits>
51 #include <utility>
52 
53 #include <folly/CPortability.h>
54 #include <folly/Traits.h>
55 #include <folly/Utility.h>
56 
57 namespace folly {
58 
59 template <class Value>
60 class Optional;
61 
62 namespace detail {
63 template <class Value>
64 struct OptionalPromiseReturn;
65 } // namespace detail
66 
67 struct None {
68   enum class _secret { _token };
69 
70   /**
71    * No default constructor to support both `op = {}` and `op = none`
72    * as syntax for clearing an Optional, just like std::nullopt_t.
73    */
NoneNone74   constexpr explicit None(_secret) {}
75 };
76 constexpr None none{None::_secret::_token};
77 
78 class FOLLY_EXPORT OptionalEmptyException : public std::runtime_error {
79  public:
OptionalEmptyException()80   OptionalEmptyException()
81       : std::runtime_error("Empty Optional cannot be unwrapped") {}
82 };
83 
84 template <class Value>
85 class Optional {
86  public:
87   typedef Value value_type;
88 
89   static_assert(
90       !std::is_reference<Value>::value,
91       "Optional may not be used with reference types");
92   static_assert(
93       !std::is_abstract<Value>::value,
94       "Optional may not be used with abstract types");
95 
Optional()96   Optional() noexcept {}
97 
noexcept(std::is_nothrow_copy_constructible<Value>::value)98   Optional(const Optional& src) noexcept(
99       std::is_nothrow_copy_constructible<Value>::value) {
100     if (src.hasValue()) {
101       construct(src.value());
102     }
103   }
104 
noexcept(std::is_nothrow_move_constructible<Value>::value)105   Optional(Optional&& src) noexcept(
106       std::is_nothrow_move_constructible<Value>::value) {
107     if (src.hasValue()) {
108       construct(std::move(src.value()));
109       src.clear();
110     }
111   }
112 
Optional(const None &)113   /* implicit */ Optional(const None&) noexcept {}
114 
noexcept(std::is_nothrow_move_constructible<Value>::value)115   /* implicit */ Optional(Value&& newValue) noexcept(
116       std::is_nothrow_move_constructible<Value>::value) {
117     construct(std::move(newValue));
118   }
119 
noexcept(std::is_nothrow_copy_constructible<Value>::value)120   /* implicit */ Optional(const Value& newValue) noexcept(
121       std::is_nothrow_copy_constructible<Value>::value) {
122     construct(newValue);
123   }
124 
125   template <typename... Args>
Optional(in_place_t,Args &&...args)126   explicit Optional(in_place_t, Args&&... args) noexcept(
127       std::is_nothrow_constructible<Value, Args...>::value)
128       : Optional{PrivateConstructor{}, std::forward<Args>(args)...} {}
129 
130   template <typename U, typename... Args>
Optional(in_place_t,std::initializer_list<U> il,Args &&...args)131   explicit Optional(
132       in_place_t,
133       std::initializer_list<U> il,
134       Args&&... args) noexcept(std::
135                                    is_nothrow_constructible<
136                                        Value,
137                                        std::initializer_list<U>,
138                                        Args...>::value)
139       : Optional{PrivateConstructor{}, il, std::forward<Args>(args)...} {}
140 
141   // Used only when an Optional is used with coroutines on MSVC
Optional(const detail::OptionalPromiseReturn<Value> & p)142   /* implicit */ Optional(const detail::OptionalPromiseReturn<Value>& p)
143       : Optional{} {
144     p.promise_->value_ = this;
145   }
146 
assign(const None &)147   void assign(const None&) {
148     clear();
149   }
150 
assign(Optional && src)151   void assign(Optional&& src) {
152     if (this != &src) {
153       if (src.hasValue()) {
154         assign(std::move(src.value()));
155         src.clear();
156       } else {
157         clear();
158       }
159     }
160   }
161 
assign(const Optional & src)162   void assign(const Optional& src) {
163     if (src.hasValue()) {
164       assign(src.value());
165     } else {
166       clear();
167     }
168   }
169 
assign(Value && newValue)170   void assign(Value&& newValue) {
171     if (hasValue()) {
172       storage_.value = std::move(newValue);
173     } else {
174       construct(std::move(newValue));
175     }
176   }
177 
assign(const Value & newValue)178   void assign(const Value& newValue) {
179     if (hasValue()) {
180       storage_.value = newValue;
181     } else {
182       construct(newValue);
183     }
184   }
185 
186   Optional& operator=(None) noexcept {
187     reset();
188     return *this;
189   }
190 
191   template <class Arg>
192   Optional& operator=(Arg&& arg) {
193     assign(std::forward<Arg>(arg));
194     return *this;
195   }
196 
noexcept(std::is_nothrow_move_assignable<Value>::value)197   Optional& operator=(Optional&& other) noexcept(
198       std::is_nothrow_move_assignable<Value>::value) {
199     assign(std::move(other));
200     return *this;
201   }
202 
noexcept(std::is_nothrow_copy_assignable<Value>::value)203   Optional& operator=(const Optional& other) noexcept(
204       std::is_nothrow_copy_assignable<Value>::value) {
205     assign(other);
206     return *this;
207   }
208 
209   template <class... Args>
emplace(Args &&...args)210   Value& emplace(Args&&... args) {
211     clear();
212     construct(std::forward<Args>(args)...);
213     return value();
214   }
215 
216   template <class U, class... Args>
217   typename std::enable_if<
218       std::is_constructible<Value, std::initializer_list<U>&, Args&&...>::value,
219       Value&>::type
emplace(std::initializer_list<U> ilist,Args &&...args)220   emplace(std::initializer_list<U> ilist, Args&&... args) {
221     clear();
222     construct(ilist, std::forward<Args>(args)...);
223     return value();
224   }
225 
reset()226   void reset() noexcept {
227     storage_.clear();
228   }
229 
clear()230   void clear() noexcept {
231     reset();
232   }
233 
swap(Optional & that)234   void swap(Optional& that) noexcept(IsNothrowSwappable<Value>::value) {
235     if (hasValue() && that.hasValue()) {
236       using std::swap;
237       swap(value(), that.value());
238     } else if (hasValue()) {
239       that.emplace(std::move(value()));
240       reset();
241     } else if (that.hasValue()) {
242       emplace(std::move(that.value()));
243       that.reset();
244     }
245   }
246 
value()247   const Value& value() const& {
248     require_value();
249     return storage_.value;
250   }
251 
value()252   Value& value() & {
253     require_value();
254     return storage_.value;
255   }
256 
value()257   Value&& value() && {
258     require_value();
259     return std::move(storage_.value);
260   }
261 
value()262   const Value&& value() const&& {
263     require_value();
264     return std::move(storage_.value);
265   }
266 
get_pointer()267   const Value* get_pointer() const& {
268     return storage_.hasValue ? &storage_.value : nullptr;
269   }
get_pointer()270   Value* get_pointer() & {
271     return storage_.hasValue ? &storage_.value : nullptr;
272   }
273   Value* get_pointer() && = delete;
274 
has_value()275   bool has_value() const noexcept {
276     return storage_.hasValue;
277   }
278 
hasValue()279   bool hasValue() const noexcept {
280     return has_value();
281   }
282 
283   explicit operator bool() const noexcept {
284     return has_value();
285   }
286 
287   const Value& operator*() const& {
288     return value();
289   }
290   Value& operator*() & {
291     return value();
292   }
293   const Value&& operator*() const&& {
294     return std::move(value());
295   }
296   Value&& operator*() && {
297     return std::move(value());
298   }
299 
300   const Value* operator->() const {
301     return &value();
302   }
303   Value* operator->() {
304     return &value();
305   }
306 
307   // Return a copy of the value if set, or a given default if not.
308   template <class U>
value_or(U && dflt)309   Value value_or(U&& dflt) const& {
310     if (storage_.hasValue) {
311       return storage_.value;
312     }
313 
314     return std::forward<U>(dflt);
315   }
316 
317   template <class U>
value_or(U && dflt)318   Value value_or(U&& dflt) && {
319     if (storage_.hasValue) {
320       return std::move(storage_.value);
321     }
322 
323     return std::forward<U>(dflt);
324   }
325 
326  private:
327   template <class T>
328   friend Optional<_t<std::decay<T>>> make_optional(T&&);
329   template <class T, class... Args>
330   friend Optional<T> make_optional(Args&&... args);
331   template <class T, class U, class... As>
332   friend Optional<T> make_optional(std::initializer_list<U>, As&&...);
333 
334   /**
335    * Construct the optional in place, this is duplicated as a non-explicit
336    * constructor to allow returning values that are non-movable from
337    * make_optional using list initialization.
338    *
339    * Until C++17, at which point this will become unnecessary because of
340    * specified prvalue elision.
341    */
342   struct PrivateConstructor {
343     explicit PrivateConstructor() = default;
344   };
345   template <typename... Args>
Optional(PrivateConstructor,Args &&...args)346   Optional(PrivateConstructor, Args&&... args) noexcept(
347       std::is_constructible<Value, Args&&...>::value) {
348     construct(std::forward<Args>(args)...);
349   }
350 
require_value()351   void require_value() const {
352     if (!storage_.hasValue) {
353       throw OptionalEmptyException{};
354     }
355   }
356 
357   template <class... Args>
construct(Args &&...args)358   void construct(Args&&... args) {
359     const void* ptr = &storage_.value;
360     // For supporting const types.
361     new (const_cast<void*>(ptr)) Value(std::forward<Args>(args)...);
362     storage_.hasValue = true;
363   }
364 
365   struct StorageTriviallyDestructible {
366     union {
367       char emptyState;
368       Value value;
369     };
370     bool hasValue;
371 
StorageTriviallyDestructibleStorageTriviallyDestructible372     StorageTriviallyDestructible()
373         : emptyState('\0'), hasValue{false} {}
clearStorageTriviallyDestructible374     void clear() {
375       hasValue = false;
376     }
377   };
378 
379   struct StorageNonTriviallyDestructible {
380     union {
381       char emptyState;
382       Value value;
383     };
384     bool hasValue;
385 
StorageNonTriviallyDestructibleStorageNonTriviallyDestructible386     StorageNonTriviallyDestructible() : hasValue{false} {}
~StorageNonTriviallyDestructibleStorageNonTriviallyDestructible387     ~StorageNonTriviallyDestructible() {
388       clear();
389     }
390 
clearStorageNonTriviallyDestructible391     void clear() {
392       if (hasValue) {
393         hasValue = false;
394         value.~Value();
395       }
396     }
397   };
398 
399   using Storage = typename std::conditional<
400       std::is_trivially_destructible<Value>::value,
401       StorageTriviallyDestructible,
402       StorageNonTriviallyDestructible>::type;
403 
404   Storage storage_;
405 };
406 
407 template <class T>
get_pointer(const Optional<T> & opt)408 const T* get_pointer(const Optional<T>& opt) {
409   return opt.get_pointer();
410 }
411 
412 template <class T>
get_pointer(Optional<T> & opt)413 T* get_pointer(Optional<T>& opt) {
414   return opt.get_pointer();
415 }
416 
417 template <class T>
swap(Optional<T> & a,Optional<T> & b)418 void swap(Optional<T>& a, Optional<T>& b) noexcept(noexcept(a.swap(b))) {
419   a.swap(b);
420 }
421 
422 template <class T>
make_optional(T && v)423 Optional<_t<std::decay<T>>> make_optional(T&& v) {
424   using PrivateConstructor =
425       typename folly::Optional<_t<std::decay<T>>>::PrivateConstructor;
426   return {PrivateConstructor{}, std::forward<T>(v)};
427 }
428 
429 template <class T, class... Args>
make_optional(Args &&...args)430 folly::Optional<T> make_optional(Args&&... args) {
431   using PrivateConstructor = typename folly::Optional<T>::PrivateConstructor;
432   return {PrivateConstructor{}, std::forward<Args>(args)...};
433 }
434 
435 template <class T, class U, class... Args>
make_optional(std::initializer_list<U> il,Args &&...args)436 folly::Optional<T> make_optional(
437     std::initializer_list<U> il,
438     Args&&... args) {
439   using PrivateConstructor = typename folly::Optional<T>::PrivateConstructor;
440   return {PrivateConstructor{}, il, std::forward<Args>(args)...};
441 }
442 
443 ///////////////////////////////////////////////////////////////////////////////
444 // Comparisons.
445 
446 template <class U, class V>
447 bool operator==(const Optional<U>& a, const V& b) {
448   return a.hasValue() && a.value() == b;
449 }
450 
451 template <class U, class V>
452 bool operator!=(const Optional<U>& a, const V& b) {
453   return !(a == b);
454 }
455 
456 template <class U, class V>
457 bool operator==(const U& a, const Optional<V>& b) {
458   return b.hasValue() && b.value() == a;
459 }
460 
461 template <class U, class V>
462 bool operator!=(const U& a, const Optional<V>& b) {
463   return !(a == b);
464 }
465 
466 template <class U, class V>
467 bool operator==(const Optional<U>& a, const Optional<V>& b) {
468   if (a.hasValue() != b.hasValue()) {
469     return false;
470   }
471   if (a.hasValue()) {
472     return a.value() == b.value();
473   }
474   return true;
475 }
476 
477 template <class U, class V>
478 bool operator!=(const Optional<U>& a, const Optional<V>& b) {
479   return !(a == b);
480 }
481 
482 template <class U, class V>
483 bool operator<(const Optional<U>& a, const Optional<V>& b) {
484   if (a.hasValue() != b.hasValue()) {
485     return a.hasValue() < b.hasValue();
486   }
487   if (a.hasValue()) {
488     return a.value() < b.value();
489   }
490   return false;
491 }
492 
493 template <class U, class V>
494 bool operator>(const Optional<U>& a, const Optional<V>& b) {
495   return b < a;
496 }
497 
498 template <class U, class V>
499 bool operator<=(const Optional<U>& a, const Optional<V>& b) {
500   return !(b < a);
501 }
502 
503 template <class U, class V>
504 bool operator>=(const Optional<U>& a, const Optional<V>& b) {
505   return !(a < b);
506 }
507 
508 // Suppress comparability of Optional<T> with T, despite implicit conversion.
509 template <class V>
510 bool operator<(const Optional<V>&, const V& other) = delete;
511 template <class V>
512 bool operator<=(const Optional<V>&, const V& other) = delete;
513 template <class V>
514 bool operator>=(const Optional<V>&, const V& other) = delete;
515 template <class V>
516 bool operator>(const Optional<V>&, const V& other) = delete;
517 template <class V>
518 bool operator<(const V& other, const Optional<V>&) = delete;
519 template <class V>
520 bool operator<=(const V& other, const Optional<V>&) = delete;
521 template <class V>
522 bool operator>=(const V& other, const Optional<V>&) = delete;
523 template <class V>
524 bool operator>(const V& other, const Optional<V>&) = delete;
525 
526 // Comparisons with none
527 template <class V>
528 bool operator==(const Optional<V>& a, None) noexcept {
529   return !a.hasValue();
530 }
531 template <class V>
532 bool operator==(None, const Optional<V>& a) noexcept {
533   return !a.hasValue();
534 }
535 template <class V>
536 bool operator<(const Optional<V>&, None) noexcept {
537   return false;
538 }
539 template <class V>
540 bool operator<(None, const Optional<V>& a) noexcept {
541   return a.hasValue();
542 }
543 template <class V>
544 bool operator>(const Optional<V>& a, None) noexcept {
545   return a.hasValue();
546 }
547 template <class V>
548 bool operator>(None, const Optional<V>&) noexcept {
549   return false;
550 }
551 template <class V>
552 bool operator<=(None, const Optional<V>&) noexcept {
553   return true;
554 }
555 template <class V>
556 bool operator<=(const Optional<V>& a, None) noexcept {
557   return !a.hasValue();
558 }
559 template <class V>
560 bool operator>=(const Optional<V>&, None) noexcept {
561   return true;
562 }
563 template <class V>
564 bool operator>=(None, const Optional<V>& a) noexcept {
565   return !a.hasValue();
566 }
567 
568 ///////////////////////////////////////////////////////////////////////////////
569 
570 } // namespace folly
571