| 1 | /* | 
| 2 |  * Copyright 2012-present Facebook, Inc. | 
| 3 |  * | 
| 4 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
| 5 |  * you may not use this file except in compliance with the License. | 
| 6 |  * You may obtain a copy of the License at | 
| 7 |  * | 
| 8 |  *   http://www.apache.org/licenses/LICENSE-2.0 | 
| 9 |  * | 
| 10 |  * Unless required by applicable law or agreed to in writing, software | 
| 11 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
| 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
| 13 |  * See the License for the specific language governing permissions and | 
| 14 |  * limitations under the License. | 
| 15 |  */ | 
| 16 | #pragma once | 
| 17 |  | 
| 18 | /* | 
| 19 |  * Optional - For conditional initialization of values, like boost::optional, | 
| 20 |  * but with support for move semantics and emplacement.  Reference type support | 
| 21 |  * has not been included due to limited use cases and potential confusion with | 
| 22 |  * semantics of assignment: Assigning to an optional reference could quite | 
| 23 |  * reasonably copy its value or redirect the reference. | 
| 24 |  * | 
| 25 |  * Optional can be useful when a variable might or might not be needed: | 
| 26 |  * | 
| 27 |  *  Optional<Logger> maybeLogger = ...; | 
| 28 |  *  if (maybeLogger) { | 
| 29 |  *    maybeLogger->log("hello"); | 
| 30 |  *  } | 
| 31 |  * | 
| 32 |  * Optional enables a 'null' value for types which do not otherwise have | 
| 33 |  * nullability, especially useful for parameter passing: | 
| 34 |  * | 
| 35 |  * void testIterator(const unique_ptr<Iterator>& it, | 
| 36 |  *                   initializer_list<int> idsExpected, | 
| 37 |  *                   Optional<initializer_list<int>> ranksExpected = none) { | 
| 38 |  *   for (int i = 0; it->next(); ++i) { | 
| 39 |  *     EXPECT_EQ(it->doc().id(), idsExpected[i]); | 
| 40 |  *     if (ranksExpected) { | 
| 41 |  *       EXPECT_EQ(it->doc().rank(), (*ranksExpected)[i]); | 
| 42 |  *     } | 
| 43 |  *   } | 
| 44 |  * } | 
| 45 |  * | 
| 46 |  * Optional models OptionalPointee, so calling 'get_pointer(opt)' will return a | 
| 47 |  * pointer to nullptr if the 'opt' is empty, and a pointer to the value if it is | 
| 48 |  * not: | 
| 49 |  * | 
| 50 |  *  Optional<int> maybeInt = ...; | 
| 51 |  *  if (int* v = get_pointer(maybeInt)) { | 
| 52 |  *    cout << *v << endl; | 
| 53 |  *  } | 
| 54 |  */ | 
| 55 |  | 
| 56 | #include <cstddef> | 
| 57 | #include <functional> | 
| 58 | #include <new> | 
| 59 | #include <stdexcept> | 
| 60 | #include <type_traits> | 
| 61 | #include <utility> | 
| 62 |  | 
| 63 | #include <folly/Portability.h> | 
| 64 | #include <folly/Traits.h> | 
| 65 | #include <folly/Utility.h> | 
| 66 | #include <folly/lang/Exception.h> | 
| 67 |  | 
| 68 | namespace folly { | 
| 69 |  | 
| 70 | template <class Value> | 
| 71 | class Optional; | 
| 72 |  | 
| 73 | namespace detail { | 
| 74 | template <class Value> | 
| 75 | struct OptionalPromiseReturn; | 
| 76 | } // namespace detail | 
| 77 |  | 
| 78 | struct None { | 
| 79 |   enum class _secret { _token }; | 
| 80 |  | 
| 81 |   /** | 
| 82 |    * No default constructor to support both `op = {}` and `op = none` | 
| 83 |    * as syntax for clearing an Optional, just like std::nullopt_t. | 
| 84 |    */ | 
| 85 |   explicit constexpr None(_secret) {} | 
| 86 | }; | 
| 87 | constexpr None none{None::_secret::_token}; | 
| 88 |  | 
| 89 | class FOLLY_EXPORT OptionalEmptyException : public std::runtime_error { | 
| 90 |  public: | 
| 91 |   OptionalEmptyException() | 
| 92 |       : std::runtime_error("Empty Optional cannot be unwrapped" ) {} | 
| 93 | }; | 
| 94 |  | 
| 95 | template <class Value> | 
| 96 | class Optional { | 
| 97 |  public: | 
| 98 |   typedef Value value_type; | 
| 99 |  | 
| 100 |   static_assert( | 
| 101 |       !std::is_reference<Value>::value, | 
| 102 |       "Optional may not be used with reference types" ); | 
| 103 |   static_assert( | 
| 104 |       !std::is_abstract<Value>::value, | 
| 105 |       "Optional may not be used with abstract types" ); | 
| 106 |  | 
| 107 |   FOLLY_CPP14_CONSTEXPR Optional() noexcept {} | 
| 108 |  | 
| 109 |   Optional(const Optional& src) noexcept( | 
| 110 |       std::is_nothrow_copy_constructible<Value>::value) { | 
| 111 |     if (src.hasValue()) { | 
| 112 |       construct(src.value()); | 
| 113 |     } | 
| 114 |   } | 
| 115 |  | 
| 116 |   Optional(Optional&& src) noexcept( | 
| 117 |       std::is_nothrow_move_constructible<Value>::value) { | 
| 118 |     if (src.hasValue()) { | 
| 119 |       construct(std::move(src.value())); | 
| 120 |       src.clear(); | 
| 121 |     } | 
| 122 |   } | 
| 123 |  | 
| 124 |   FOLLY_CPP14_CONSTEXPR /* implicit */ Optional(const None&) noexcept {} | 
| 125 |  | 
| 126 |   FOLLY_CPP14_CONSTEXPR /* implicit */ Optional(Value&& newValue) noexcept( | 
| 127 |       std::is_nothrow_move_constructible<Value>::value) { | 
| 128 |     construct(std::move(newValue)); | 
| 129 |   } | 
| 130 |  | 
| 131 |   FOLLY_CPP14_CONSTEXPR /* implicit */ Optional(const Value& newValue) noexcept( | 
| 132 |       std::is_nothrow_copy_constructible<Value>::value) { | 
| 133 |     construct(newValue); | 
| 134 |   } | 
| 135 |  | 
| 136 |   /** | 
| 137 |    * Explicitly disallow converting nullptr to non-pointer | 
| 138 |    * types. Optional used to support initialization from nullptr as if | 
| 139 |    * it were folly::none. Without this constructor, | 
| 140 |    * folly::Optional<bool> could be constructed from nullptr, | 
| 141 |    * producing {false} instead of {}. This would be a change in | 
| 142 |    * behavior from the old code, so explicitly disallow it. Note that | 
| 143 |    * std::optional<bool> can be constructed from nullptr, also | 
| 144 |    * producing {false}. | 
| 145 |    * | 
| 146 |    * This constructor is temporary and should be removed when all call | 
| 147 |    * sites are fixed. | 
| 148 |    */ | 
| 149 |   template <typename Null = std::nullptr_t> | 
| 150 |   /* implicit */ | 
| 151 |   Optional(typename std::enable_if< | 
| 152 |            std::is_convertible<Null, Value>::value, | 
| 153 |            Null>::type) noexcept = delete; | 
| 154 |  | 
| 155 |   template <typename... Args> | 
| 156 |   FOLLY_CPP14_CONSTEXPR explicit Optional(in_place_t, Args&&... args) noexcept( | 
| 157 |       std::is_nothrow_constructible<Value, Args...>::value) | 
| 158 |       : Optional{PrivateConstructor{}, std::forward<Args>(args)...} {} | 
| 159 |  | 
| 160 |   template <typename U, typename... Args> | 
| 161 |   FOLLY_CPP14_CONSTEXPR explicit Optional( | 
| 162 |       in_place_t, | 
| 163 |       std::initializer_list<U> il, | 
| 164 |       Args&&... args) noexcept(std:: | 
| 165 |                                    is_nothrow_constructible< | 
| 166 |                                        Value, | 
| 167 |                                        std::initializer_list<U>, | 
| 168 |                                        Args...>::value) | 
| 169 |       : Optional{PrivateConstructor{}, il, std::forward<Args>(args)...} {} | 
| 170 |  | 
| 171 |   // Used only when an Optional is used with coroutines on MSVC | 
| 172 |   /* implicit */ Optional(const detail::OptionalPromiseReturn<Value>& p) | 
| 173 |       : Optional{} { | 
| 174 |     p.promise_->value_ = this; | 
| 175 |   } | 
| 176 |  | 
| 177 |   void assign(const None&) { | 
| 178 |     clear(); | 
| 179 |   } | 
| 180 |  | 
| 181 |   void assign(Optional&& src) { | 
| 182 |     if (this != &src) { | 
| 183 |       if (src.hasValue()) { | 
| 184 |         assign(std::move(src.value())); | 
| 185 |         src.clear(); | 
| 186 |       } else { | 
| 187 |         clear(); | 
| 188 |       } | 
| 189 |     } | 
| 190 |   } | 
| 191 |  | 
| 192 |   void assign(const Optional& src) { | 
| 193 |     if (src.hasValue()) { | 
| 194 |       assign(src.value()); | 
| 195 |     } else { | 
| 196 |       clear(); | 
| 197 |     } | 
| 198 |   } | 
| 199 |  | 
| 200 |   void assign(Value&& newValue) { | 
| 201 |     if (hasValue()) { | 
| 202 |       storage_.value = std::move(newValue); | 
| 203 |     } else { | 
| 204 |       construct(std::move(newValue)); | 
| 205 |     } | 
| 206 |   } | 
| 207 |  | 
| 208 |   void assign(const Value& newValue) { | 
| 209 |     if (hasValue()) { | 
| 210 |       storage_.value = newValue; | 
| 211 |     } else { | 
| 212 |       construct(newValue); | 
| 213 |     } | 
| 214 |   } | 
| 215 |  | 
| 216 |   Optional& operator=(None) noexcept { | 
| 217 |     reset(); | 
| 218 |     return *this; | 
| 219 |   } | 
| 220 |  | 
| 221 |   template <class Arg> | 
| 222 |   Optional& operator=(Arg&& arg) { | 
| 223 |     assign(std::forward<Arg>(arg)); | 
| 224 |     return *this; | 
| 225 |   } | 
| 226 |  | 
| 227 |   Optional& operator=(Optional&& other) noexcept( | 
| 228 |       std::is_nothrow_move_assignable<Value>::value) { | 
| 229 |     assign(std::move(other)); | 
| 230 |     return *this; | 
| 231 |   } | 
| 232 |  | 
| 233 |   Optional& operator=(const Optional& other) noexcept( | 
| 234 |       std::is_nothrow_copy_assignable<Value>::value) { | 
| 235 |     assign(other); | 
| 236 |     return *this; | 
| 237 |   } | 
| 238 |  | 
| 239 |   template <class... Args> | 
| 240 |   Value& emplace(Args&&... args) { | 
| 241 |     clear(); | 
| 242 |     construct(std::forward<Args>(args)...); | 
| 243 |     return value(); | 
| 244 |   } | 
| 245 |  | 
| 246 |   template <class U, class... Args> | 
| 247 |   typename std::enable_if< | 
| 248 |       std::is_constructible<Value, std::initializer_list<U>&, Args&&...>::value, | 
| 249 |       Value&>::type | 
| 250 |   emplace(std::initializer_list<U> ilist, Args&&... args) { | 
| 251 |     clear(); | 
| 252 |     construct(ilist, std::forward<Args>(args)...); | 
| 253 |     return value(); | 
| 254 |   } | 
| 255 |  | 
| 256 |   void reset() noexcept { | 
| 257 |     storage_.clear(); | 
| 258 |   } | 
| 259 |  | 
| 260 |   void clear() noexcept { | 
| 261 |     reset(); | 
| 262 |   } | 
| 263 |  | 
| 264 |   void swap(Optional& that) noexcept(IsNothrowSwappable<Value>::value) { | 
| 265 |     if (hasValue() && that.hasValue()) { | 
| 266 |       using std::swap; | 
| 267 |       swap(value(), that.value()); | 
| 268 |     } else if (hasValue()) { | 
| 269 |       that.emplace(std::move(value())); | 
| 270 |       reset(); | 
| 271 |     } else if (that.hasValue()) { | 
| 272 |       emplace(std::move(that.value())); | 
| 273 |       that.reset(); | 
| 274 |     } | 
| 275 |   } | 
| 276 |  | 
| 277 |   FOLLY_CPP14_CONSTEXPR const Value& value() const& { | 
| 278 |     require_value(); | 
| 279 |     return storage_.value; | 
| 280 |   } | 
| 281 |  | 
| 282 |   FOLLY_CPP14_CONSTEXPR Value& value() & { | 
| 283 |     require_value(); | 
| 284 |     return storage_.value; | 
| 285 |   } | 
| 286 |  | 
| 287 |   FOLLY_CPP14_CONSTEXPR Value&& value() && { | 
| 288 |     require_value(); | 
| 289 |     return std::move(storage_.value); | 
| 290 |   } | 
| 291 |  | 
| 292 |   FOLLY_CPP14_CONSTEXPR const Value&& value() const&& { | 
| 293 |     require_value(); | 
| 294 |     return std::move(storage_.value); | 
| 295 |   } | 
| 296 |  | 
| 297 |   const Value* get_pointer() const& { | 
| 298 |     return storage_.hasValue ? &storage_.value : nullptr; | 
| 299 |   } | 
| 300 |   Value* get_pointer() & { | 
| 301 |     return storage_.hasValue ? &storage_.value : nullptr; | 
| 302 |   } | 
| 303 |   Value* get_pointer() && = delete; | 
| 304 |  | 
| 305 |   FOLLY_CPP14_CONSTEXPR bool has_value() const noexcept { | 
| 306 |     return storage_.hasValue; | 
| 307 |   } | 
| 308 |  | 
| 309 |   FOLLY_CPP14_CONSTEXPR bool hasValue() const noexcept { | 
| 310 |     return has_value(); | 
| 311 |   } | 
| 312 |  | 
| 313 |   FOLLY_CPP14_CONSTEXPR explicit operator bool() const noexcept { | 
| 314 |     return has_value(); | 
| 315 |   } | 
| 316 |  | 
| 317 |   FOLLY_CPP14_CONSTEXPR const Value& operator*() const& { | 
| 318 |     return value(); | 
| 319 |   } | 
| 320 |   FOLLY_CPP14_CONSTEXPR Value& operator*() & { | 
| 321 |     return value(); | 
| 322 |   } | 
| 323 |   FOLLY_CPP14_CONSTEXPR const Value&& operator*() const&& { | 
| 324 |     return std::move(value()); | 
| 325 |   } | 
| 326 |   FOLLY_CPP14_CONSTEXPR Value&& operator*() && { | 
| 327 |     return std::move(value()); | 
| 328 |   } | 
| 329 |  | 
| 330 |   FOLLY_CPP14_CONSTEXPR const Value* operator->() const { | 
| 331 |     return &value(); | 
| 332 |   } | 
| 333 |   FOLLY_CPP14_CONSTEXPR Value* operator->() { | 
| 334 |     return &value(); | 
| 335 |   } | 
| 336 |  | 
| 337 |   // Return a copy of the value if set, or a given default if not. | 
| 338 |   template <class U> | 
| 339 |   FOLLY_CPP14_CONSTEXPR Value value_or(U&& dflt) const& { | 
| 340 |     if (storage_.hasValue) { | 
| 341 |       return storage_.value; | 
| 342 |     } | 
| 343 |  | 
| 344 |     return std::forward<U>(dflt); | 
| 345 |   } | 
| 346 |  | 
| 347 |   template <class U> | 
| 348 |   FOLLY_CPP14_CONSTEXPR Value value_or(U&& dflt) && { | 
| 349 |     if (storage_.hasValue) { | 
| 350 |       return std::move(storage_.value); | 
| 351 |     } | 
| 352 |  | 
| 353 |     return std::forward<U>(dflt); | 
| 354 |   } | 
| 355 |  | 
| 356 |  private: | 
| 357 |   template <class T> | 
| 358 |   friend constexpr Optional<std::decay_t<T>> make_optional(T&&); | 
| 359 |   template <class T, class... Args> | 
| 360 |   friend constexpr Optional<T> make_optional(Args&&... args); | 
| 361 |   template <class T, class U, class... As> | 
| 362 |   friend constexpr Optional<T> make_optional(std::initializer_list<U>, As&&...); | 
| 363 |  | 
| 364 |   /** | 
| 365 |    * Construct the optional in place, this is duplicated as a non-explicit | 
| 366 |    * constructor to allow returning values that are non-movable from | 
| 367 |    * make_optional using list initialization. | 
| 368 |    * | 
| 369 |    * Until C++17, at which point this will become unnecessary because of | 
| 370 |    * specified prvalue elision. | 
| 371 |    */ | 
| 372 |   struct PrivateConstructor { | 
| 373 |     explicit PrivateConstructor() = default; | 
| 374 |   }; | 
| 375 |   template <typename... Args> | 
| 376 |   FOLLY_CPP14_CONSTEXPR Optional(PrivateConstructor, Args&&... args) noexcept( | 
| 377 |       std::is_constructible<Value, Args&&...>::value) { | 
| 378 |     construct(std::forward<Args>(args)...); | 
| 379 |   } | 
| 380 |  | 
| 381 |   void require_value() const { | 
| 382 |     if (!storage_.hasValue) { | 
| 383 |       throw_exception<OptionalEmptyException>(); | 
| 384 |     } | 
| 385 |   } | 
| 386 |  | 
| 387 |   template <class... Args> | 
| 388 |   void construct(Args&&... args) { | 
| 389 |     const void* ptr = &storage_.value; | 
| 390 |     // For supporting const types. | 
| 391 |     new (const_cast<void*>(ptr)) Value(std::forward<Args>(args)...); | 
| 392 |     storage_.hasValue = true; | 
| 393 |   } | 
| 394 |  | 
| 395 |   struct StorageTriviallyDestructible { | 
| 396 |     union { | 
| 397 |       char emptyState; | 
| 398 |       Value value; | 
| 399 |     }; | 
| 400 |     bool hasValue; | 
| 401 |  | 
| 402 |     StorageTriviallyDestructible() : hasValue{false} {} | 
| 403 |     void clear() { | 
| 404 |       hasValue = false; | 
| 405 |     } | 
| 406 |   }; | 
| 407 |  | 
| 408 |   struct StorageNonTriviallyDestructible { | 
| 409 |     union { | 
| 410 |       char emptyState; | 
| 411 |       Value value; | 
| 412 |     }; | 
| 413 |     bool hasValue; | 
| 414 |  | 
| 415 |     FOLLY_PUSH_WARNING | 
| 416 |     // These are both informational warnings, but they trigger rare | 
| 417 |     // enough that we've left them enabled. Needed as long as MSVC | 
| 418 |     // 2015 is supported. | 
| 419 |     FOLLY_MSVC_DISABLE_WARNING(4587) // constructor of .value is not called | 
| 420 |     FOLLY_MSVC_DISABLE_WARNING(4588) // destructor of .value is not called | 
| 421 |     StorageNonTriviallyDestructible() : hasValue{false} {} | 
| 422 |     ~StorageNonTriviallyDestructible() { | 
| 423 |       clear(); | 
| 424 |     } | 
| 425 |     FOLLY_POP_WARNING | 
| 426 |  | 
| 427 |     void clear() { | 
| 428 |       if (hasValue) { | 
| 429 |         hasValue = false; | 
| 430 |         value.~Value(); | 
| 431 |       } | 
| 432 |     } | 
| 433 |   }; | 
| 434 |  | 
| 435 |   using Storage = typename std::conditional< | 
| 436 |       std::is_trivially_destructible<Value>::value, | 
| 437 |       StorageTriviallyDestructible, | 
| 438 |       StorageNonTriviallyDestructible>::type; | 
| 439 |  | 
| 440 |   Storage storage_; | 
| 441 | }; | 
| 442 |  | 
| 443 | template <class T> | 
| 444 | const T* get_pointer(const Optional<T>& opt) { | 
| 445 |   return opt.get_pointer(); | 
| 446 | } | 
| 447 |  | 
| 448 | template <class T> | 
| 449 | T* get_pointer(Optional<T>& opt) { | 
| 450 |   return opt.get_pointer(); | 
| 451 | } | 
| 452 |  | 
| 453 | template <class T> | 
| 454 | void swap(Optional<T>& a, Optional<T>& b) noexcept(noexcept(a.swap(b))) { | 
| 455 |   a.swap(b); | 
| 456 | } | 
| 457 |  | 
| 458 | template <class T> | 
| 459 | constexpr Optional<std::decay_t<T>> make_optional(T&& v) { | 
| 460 |   using PrivateConstructor = | 
| 461 |       typename folly::Optional<std::decay_t<T>>::PrivateConstructor; | 
| 462 |   return {PrivateConstructor{}, std::forward<T>(v)}; | 
| 463 | } | 
| 464 |  | 
| 465 | template <class T, class... Args> | 
| 466 | constexpr folly::Optional<T> make_optional(Args&&... args) { | 
| 467 |   using PrivateConstructor = typename folly::Optional<T>::PrivateConstructor; | 
| 468 |   return {PrivateConstructor{}, std::forward<Args>(args)...}; | 
| 469 | } | 
| 470 |  | 
| 471 | template <class T, class U, class... Args> | 
| 472 | constexpr folly::Optional<T> make_optional( | 
| 473 |     std::initializer_list<U> il, | 
| 474 |     Args&&... args) { | 
| 475 |   using PrivateConstructor = typename folly::Optional<T>::PrivateConstructor; | 
| 476 |   return {PrivateConstructor{}, il, std::forward<Args>(args)...}; | 
| 477 | } | 
| 478 |  | 
| 479 | /////////////////////////////////////////////////////////////////////////////// | 
| 480 | // Comparisons. | 
| 481 |  | 
| 482 | template <class U, class V> | 
| 483 | constexpr bool operator==(const Optional<U>& a, const V& b) { | 
| 484 |   return a.hasValue() && a.value() == b; | 
| 485 | } | 
| 486 |  | 
| 487 | template <class U, class V> | 
| 488 | constexpr bool operator!=(const Optional<U>& a, const V& b) { | 
| 489 |   return !(a == b); | 
| 490 | } | 
| 491 |  | 
| 492 | template <class U, class V> | 
| 493 | constexpr bool operator==(const U& a, const Optional<V>& b) { | 
| 494 |   return b.hasValue() && b.value() == a; | 
| 495 | } | 
| 496 |  | 
| 497 | template <class U, class V> | 
| 498 | constexpr bool operator!=(const U& a, const Optional<V>& b) { | 
| 499 |   return !(a == b); | 
| 500 | } | 
| 501 |  | 
| 502 | template <class U, class V> | 
| 503 | FOLLY_CPP14_CONSTEXPR bool operator==( | 
| 504 |     const Optional<U>& a, | 
| 505 |     const Optional<V>& b) { | 
| 506 |   if (a.hasValue() != b.hasValue()) { | 
| 507 |     return false; | 
| 508 |   } | 
| 509 |   if (a.hasValue()) { | 
| 510 |     return a.value() == b.value(); | 
| 511 |   } | 
| 512 |   return true; | 
| 513 | } | 
| 514 |  | 
| 515 | template <class U, class V> | 
| 516 | constexpr bool operator!=(const Optional<U>& a, const Optional<V>& b) { | 
| 517 |   return !(a == b); | 
| 518 | } | 
| 519 |  | 
| 520 | template <class U, class V> | 
| 521 | FOLLY_CPP14_CONSTEXPR bool operator<( | 
| 522 |     const Optional<U>& a, | 
| 523 |     const Optional<V>& b) { | 
| 524 |   if (a.hasValue() != b.hasValue()) { | 
| 525 |     return a.hasValue() < b.hasValue(); | 
| 526 |   } | 
| 527 |   if (a.hasValue()) { | 
| 528 |     return a.value() < b.value(); | 
| 529 |   } | 
| 530 |   return false; | 
| 531 | } | 
| 532 |  | 
| 533 | template <class U, class V> | 
| 534 | constexpr bool operator>(const Optional<U>& a, const Optional<V>& b) { | 
| 535 |   return b < a; | 
| 536 | } | 
| 537 |  | 
| 538 | template <class U, class V> | 
| 539 | constexpr bool operator<=(const Optional<U>& a, const Optional<V>& b) { | 
| 540 |   return !(b < a); | 
| 541 | } | 
| 542 |  | 
| 543 | template <class U, class V> | 
| 544 | constexpr bool operator>=(const Optional<U>& a, const Optional<V>& b) { | 
| 545 |   return !(a < b); | 
| 546 | } | 
| 547 |  | 
| 548 | // Suppress comparability of Optional<T> with T, despite implicit conversion. | 
| 549 | template <class V> | 
| 550 | bool operator<(const Optional<V>&, const V& other) = delete; | 
| 551 | template <class V> | 
| 552 | bool operator<=(const Optional<V>&, const V& other) = delete; | 
| 553 | template <class V> | 
| 554 | bool operator>=(const Optional<V>&, const V& other) = delete; | 
| 555 | template <class V> | 
| 556 | bool operator>(const Optional<V>&, const V& other) = delete; | 
| 557 | template <class V> | 
| 558 | bool operator<(const V& other, const Optional<V>&) = delete; | 
| 559 | template <class V> | 
| 560 | bool operator<=(const V& other, const Optional<V>&) = delete; | 
| 561 | template <class V> | 
| 562 | bool operator>=(const V& other, const Optional<V>&) = delete; | 
| 563 | template <class V> | 
| 564 | bool operator>(const V& other, const Optional<V>&) = delete; | 
| 565 |  | 
| 566 | // Comparisons with none | 
| 567 | template <class V> | 
| 568 | constexpr bool operator==(const Optional<V>& a, None) noexcept { | 
| 569 |   return !a.hasValue(); | 
| 570 | } | 
| 571 | template <class V> | 
| 572 | constexpr bool operator==(None, const Optional<V>& a) noexcept { | 
| 573 |   return !a.hasValue(); | 
| 574 | } | 
| 575 | template <class V> | 
| 576 | constexpr bool operator<(const Optional<V>&, None) noexcept { | 
| 577 |   return false; | 
| 578 | } | 
| 579 | template <class V> | 
| 580 | constexpr bool operator<(None, const Optional<V>& a) noexcept { | 
| 581 |   return a.hasValue(); | 
| 582 | } | 
| 583 | template <class V> | 
| 584 | constexpr bool operator>(const Optional<V>& a, None) noexcept { | 
| 585 |   return a.hasValue(); | 
| 586 | } | 
| 587 | template <class V> | 
| 588 | constexpr bool operator>(None, const Optional<V>&) noexcept { | 
| 589 |   return false; | 
| 590 | } | 
| 591 | template <class V> | 
| 592 | constexpr bool operator<=(None, const Optional<V>&) noexcept { | 
| 593 |   return true; | 
| 594 | } | 
| 595 | template <class V> | 
| 596 | constexpr bool operator<=(const Optional<V>& a, None) noexcept { | 
| 597 |   return !a.hasValue(); | 
| 598 | } | 
| 599 | template <class V> | 
| 600 | constexpr bool operator>=(const Optional<V>&, None) noexcept { | 
| 601 |   return true; | 
| 602 | } | 
| 603 | template <class V> | 
| 604 | constexpr bool operator>=(None, const Optional<V>& a) noexcept { | 
| 605 |   return !a.hasValue(); | 
| 606 | } | 
| 607 |  | 
| 608 | /////////////////////////////////////////////////////////////////////////////// | 
| 609 |  | 
| 610 | } // namespace folly | 
| 611 |  | 
| 612 | // Allow usage of Optional<T> in std::unordered_map and std::unordered_set | 
| 613 | FOLLY_NAMESPACE_STD_BEGIN | 
| 614 | template <class T> | 
| 615 | struct hash<folly::Optional<T>> { | 
| 616 |   size_t operator()(folly::Optional<T> const& obj) const { | 
| 617 |     if (!obj.hasValue()) { | 
| 618 |       return 0; | 
| 619 |     } | 
| 620 |     return hash<typename remove_const<T>::type>()(*obj); | 
| 621 |   } | 
| 622 | }; | 
| 623 | FOLLY_NAMESPACE_STD_END | 
| 624 |  | 
| 625 | // Enable the use of folly::Optional with `co_await` | 
| 626 | // Inspired by https://github.com/toby-allsopp/coroutine_monad | 
| 627 | #if FOLLY_HAS_COROUTINES | 
| 628 | #include <experimental/coroutine> | 
| 629 |  | 
| 630 | namespace folly { | 
| 631 | namespace detail { | 
| 632 | template <typename Value> | 
| 633 | struct OptionalPromise; | 
| 634 |  | 
| 635 | template <typename Value> | 
| 636 | struct OptionalPromiseReturn { | 
| 637 |   Optional<Value> storage_; | 
| 638 |   OptionalPromise<Value>* promise_; | 
| 639 |   /* implicit */ OptionalPromiseReturn(OptionalPromise<Value>& promise) noexcept | 
| 640 |       : promise_(&promise) { | 
| 641 |     promise.value_ = &storage_; | 
| 642 |   } | 
| 643 |   OptionalPromiseReturn(OptionalPromiseReturn&& that) noexcept | 
| 644 |       : OptionalPromiseReturn{*that.promise_} {} | 
| 645 |   ~OptionalPromiseReturn() {} | 
| 646 |   /* implicit */ operator Optional<Value>() & { | 
| 647 |     return std::move(storage_); | 
| 648 |   } | 
| 649 | }; | 
| 650 |  | 
| 651 | template <typename Value> | 
| 652 | struct OptionalPromise { | 
| 653 |   Optional<Value>* value_ = nullptr; | 
| 654 |   OptionalPromise() = default; | 
| 655 |   OptionalPromise(OptionalPromise const&) = delete; | 
| 656 |   // This should work regardless of whether the compiler generates: | 
| 657 |   //    folly::Optional<Value> retobj{ p.get_return_object(); } // MSVC | 
| 658 |   // or: | 
| 659 |   //    auto retobj = p.get_return_object(); // clang | 
| 660 |   OptionalPromiseReturn<Value> get_return_object() noexcept { | 
| 661 |     return *this; | 
| 662 |   } | 
| 663 |   std::experimental::suspend_never initial_suspend() const noexcept { | 
| 664 |     return {}; | 
| 665 |   } | 
| 666 |   std::experimental::suspend_never final_suspend() const { | 
| 667 |     return {}; | 
| 668 |   } | 
| 669 |   template <typename U> | 
| 670 |   void return_value(U&& u) { | 
| 671 |     *value_ = static_cast<U&&>(u); | 
| 672 |   } | 
| 673 |   void unhandled_exception() { | 
| 674 |     // Technically, throwing from unhandled_exception is underspecified: | 
| 675 |     // https://github.com/GorNishanov/CoroutineWording/issues/17 | 
| 676 |     throw; | 
| 677 |   } | 
| 678 | }; | 
| 679 |  | 
| 680 | template <typename Value> | 
| 681 | struct OptionalAwaitable { | 
| 682 |   Optional<Value> o_; | 
| 683 |   bool await_ready() const noexcept { | 
| 684 |     return o_.hasValue(); | 
| 685 |   } | 
| 686 |   Value await_resume() { | 
| 687 |     return std::move(o_.value()); | 
| 688 |   } | 
| 689 |  | 
| 690 |   // Explicitly only allow suspension into an OptionalPromise | 
| 691 |   template <typename U> | 
| 692 |   void await_suspend( | 
| 693 |       std::experimental::coroutine_handle<OptionalPromise<U>> h) const { | 
| 694 |     // Abort the rest of the coroutine. resume() is not going to be called | 
| 695 |     h.destroy(); | 
| 696 |   } | 
| 697 | }; | 
| 698 | } // namespace detail | 
| 699 |  | 
| 700 | template <typename Value> | 
| 701 | detail::OptionalAwaitable<Value> | 
| 702 | /* implicit */ operator co_await(Optional<Value> o) { | 
| 703 |   return {std::move(o)}; | 
| 704 | } | 
| 705 | } // namespace folly | 
| 706 |  | 
| 707 | // This makes folly::Optional<Value> useable as a coroutine return type.. | 
| 708 | namespace std { | 
| 709 | namespace experimental { | 
| 710 | template <typename Value, typename... Args> | 
| 711 | struct coroutine_traits<folly::Optional<Value>, Args...> { | 
| 712 |   using promise_type = folly::detail::OptionalPromise<Value>; | 
| 713 | }; | 
| 714 | } // namespace experimental | 
| 715 | } // namespace std | 
| 716 | #endif // FOLLY_HAS_COROUTINES | 
| 717 |  |