1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_OPTIONAL_H_ 6 #define BASE_OPTIONAL_H_ 7 8 #include <type_traits> 9 #include <utility> 10 11 #include "base/logging.h" 12 #include "base/template_util.h" 13 14 namespace base { 15 16 // Specification: 17 // http://en.cppreference.com/w/cpp/utility/optional/in_place_t 18 struct in_place_t {}; 19 20 // Specification: 21 // http://en.cppreference.com/w/cpp/utility/optional/nullopt_t 22 struct nullopt_t { nullopt_tnullopt_t23 constexpr explicit nullopt_t(int) {} 24 }; 25 26 // Specification: 27 // http://en.cppreference.com/w/cpp/utility/optional/in_place 28 constexpr in_place_t in_place = {}; 29 30 // Specification: 31 // http://en.cppreference.com/w/cpp/utility/optional/nullopt 32 constexpr nullopt_t nullopt(0); 33 34 // Forward declaration, which is refered by following helpers. 35 template <typename T> 36 class Optional; 37 38 namespace internal { 39 40 template <typename T, bool = std::is_trivially_destructible<T>::value> 41 struct OptionalStorageBase { 42 // Initializing |empty_| here instead of using default member initializing 43 // to avoid errors in g++ 4.8. OptionalStorageBaseOptionalStorageBase44 constexpr OptionalStorageBase() : empty_('\0') {} 45 46 template <class... Args> OptionalStorageBaseOptionalStorageBase47 constexpr explicit OptionalStorageBase(in_place_t, Args&&... args) 48 : is_populated_(true), value_(std::forward<Args>(args)...) {} 49 50 // When T is not trivially destructible we must call its 51 // destructor before deallocating its memory. 52 // Note that this hides the (implicitly declared) move constructor, which 53 // would be used for constexpr move constructor in OptionalStorage<T>. 54 // It is needed iff T is trivially move constructible. However, the current 55 // is_trivially_{copy,move}_constructible implementation requires 56 // is_trivially_destructible (which looks a bug, cf: 57 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 and 58 // http://cplusplus.github.io/LWG/lwg-active.html#2116), so it is not 59 // necessary for this case at the moment. Please see also the destructor 60 // comment in "is_trivially_destructible = true" specialization below. ~OptionalStorageBaseOptionalStorageBase61 ~OptionalStorageBase() { 62 if (is_populated_) 63 value_.~T(); 64 } 65 66 template <class... Args> InitOptionalStorageBase67 void Init(Args&&... args) { 68 DCHECK(!is_populated_); 69 ::new (&value_) T(std::forward<Args>(args)...); 70 is_populated_ = true; 71 } 72 73 bool is_populated_ = false; 74 union { 75 // |empty_| exists so that the union will always be initialized, even when 76 // it doesn't contain a value. Union members must be initialized for the 77 // constructor to be 'constexpr'. 78 char empty_; 79 T value_; 80 }; 81 }; 82 83 template <typename T> 84 struct OptionalStorageBase<T, true /* trivially destructible */> { 85 // Initializing |empty_| here instead of using default member initializing 86 // to avoid errors in g++ 4.8. 87 constexpr OptionalStorageBase() : empty_('\0') {} 88 89 template <class... Args> 90 constexpr explicit OptionalStorageBase(in_place_t, Args&&... args) 91 : is_populated_(true), value_(std::forward<Args>(args)...) {} 92 93 // When T is trivially destructible (i.e. its destructor does nothing) there 94 // is no need to call it. Implicitly defined destructor is trivial, because 95 // both members (bool and union containing only variants which are trivially 96 // destructible) are trivially destructible. 97 // Explicitly-defaulted destructor is also trivial, but do not use it here, 98 // because it hides the implicit move constructor. It is needed to implement 99 // constexpr move constructor in OptionalStorage iff T is trivially move 100 // constructible. Note that, if T is trivially move constructible, the move 101 // constructor of OptionalStorageBase<T> is also implicitly defined and it is 102 // trivially move constructor. If T is not trivially move constructible, 103 // "not declaring move constructor without destructor declaration" here means 104 // "delete move constructor", which works because any move constructor of 105 // OptionalStorage will not refer to it in that case. 106 107 template <class... Args> 108 void Init(Args&&... args) { 109 DCHECK(!is_populated_); 110 ::new (&value_) T(std::forward<Args>(args)...); 111 is_populated_ = true; 112 } 113 114 bool is_populated_ = false; 115 union { 116 // |empty_| exists so that the union will always be initialized, even when 117 // it doesn't contain a value. Union members must be initialized for the 118 // constructor to be 'constexpr'. 119 char empty_; 120 T value_; 121 }; 122 }; 123 124 // Implement conditional constexpr copy and move constructors. These are 125 // constexpr if is_trivially_{copy,move}_constructible<T>::value is true 126 // respectively. If each is true, the corresponding constructor is defined as 127 // "= default;", which generates a constexpr constructor (In this case, 128 // the condition of constexpr-ness is satisfied because the base class also has 129 // compiler generated constexpr {copy,move} constructors). Note that 130 // placement-new is prohibited in constexpr. 131 template <typename T, 132 bool = is_trivially_copy_constructible<T>::value, 133 bool = std::is_trivially_move_constructible<T>::value> 134 struct OptionalStorage : OptionalStorageBase<T> { 135 // This is no trivially {copy,move} constructible case. Other cases are 136 // defined below as specializations. 137 138 // Accessing the members of template base class requires explicit 139 // declaration. 140 using OptionalStorageBase<T>::is_populated_; 141 using OptionalStorageBase<T>::value_; 142 using OptionalStorageBase<T>::Init; 143 144 // Inherit constructors (specifically, the in_place constructor). 145 using OptionalStorageBase<T>::OptionalStorageBase; 146 147 // User defined constructor deletes the default constructor. 148 // Define it explicitly. 149 OptionalStorage() = default; 150 151 OptionalStorage(const OptionalStorage& other) { 152 if (other.is_populated_) 153 Init(other.value_); 154 } 155 156 OptionalStorage(OptionalStorage&& other) noexcept( 157 std::is_nothrow_move_constructible<T>::value) { 158 if (other.is_populated_) 159 Init(std::move(other.value_)); 160 } 161 }; 162 163 template <typename T> 164 struct OptionalStorage<T, 165 true /* trivially copy constructible */, 166 false /* trivially move constructible */> 167 : OptionalStorageBase<T> { 168 using OptionalStorageBase<T>::is_populated_; 169 using OptionalStorageBase<T>::value_; 170 using OptionalStorageBase<T>::Init; 171 using OptionalStorageBase<T>::OptionalStorageBase; 172 173 OptionalStorage() = default; 174 OptionalStorage(const OptionalStorage& other) = default; 175 176 OptionalStorage(OptionalStorage&& other) noexcept( 177 std::is_nothrow_move_constructible<T>::value) { 178 if (other.is_populated_) 179 Init(std::move(other.value_)); 180 } 181 }; 182 183 template <typename T> 184 struct OptionalStorage<T, 185 false /* trivially copy constructible */, 186 true /* trivially move constructible */> 187 : OptionalStorageBase<T> { 188 using OptionalStorageBase<T>::is_populated_; 189 using OptionalStorageBase<T>::value_; 190 using OptionalStorageBase<T>::Init; 191 using OptionalStorageBase<T>::OptionalStorageBase; 192 193 OptionalStorage() = default; 194 OptionalStorage(OptionalStorage&& other) = default; 195 196 OptionalStorage(const OptionalStorage& other) { 197 if (other.is_populated_) 198 Init(other.value_); 199 } 200 }; 201 202 template <typename T> 203 struct OptionalStorage<T, 204 true /* trivially copy constructible */, 205 true /* trivially move constructible */> 206 : OptionalStorageBase<T> { 207 // If both trivially {copy,move} constructible are true, it is not necessary 208 // to use user-defined constructors. So, just inheriting constructors 209 // from the base class works. 210 using OptionalStorageBase<T>::OptionalStorageBase; 211 }; 212 213 // Base class to support conditionally usable copy-/move- constructors 214 // and assign operators. 215 template <typename T> 216 class OptionalBase { 217 // This class provides implementation rather than public API, so everything 218 // should be hidden. Often we use composition, but we cannot in this case 219 // because of C++ language restriction. 220 protected: 221 constexpr OptionalBase() = default; 222 constexpr OptionalBase(const OptionalBase& other) = default; 223 constexpr OptionalBase(OptionalBase&& other) = default; 224 225 template <class... Args> 226 constexpr explicit OptionalBase(in_place_t, Args&&... args) 227 : storage_(in_place, std::forward<Args>(args)...) {} 228 229 // Implementation of converting constructors. 230 template <typename U> 231 explicit OptionalBase(const OptionalBase<U>& other) { 232 if (other.storage_.is_populated_) 233 storage_.Init(other.storage_.value_); 234 } 235 236 template <typename U> 237 explicit OptionalBase(OptionalBase<U>&& other) { 238 if (other.storage_.is_populated_) 239 storage_.Init(std::move(other.storage_.value_)); 240 } 241 242 ~OptionalBase() = default; 243 244 OptionalBase& operator=(const OptionalBase& other) { 245 CopyAssign(other); 246 return *this; 247 } 248 249 OptionalBase& operator=(OptionalBase&& other) noexcept( 250 std::is_nothrow_move_assignable<T>::value&& 251 std::is_nothrow_move_constructible<T>::value) { 252 MoveAssign(std::move(other)); 253 return *this; 254 } 255 256 template <typename U> 257 void CopyAssign(const OptionalBase<U>& other) { 258 if (other.storage_.is_populated_) 259 InitOrAssign(other.storage_.value_); 260 else 261 FreeIfNeeded(); 262 } 263 264 template <typename U> 265 void MoveAssign(OptionalBase<U>&& other) { 266 if (other.storage_.is_populated_) 267 InitOrAssign(std::move(other.storage_.value_)); 268 else 269 FreeIfNeeded(); 270 } 271 272 template <typename U> 273 void InitOrAssign(U&& value) { 274 if (storage_.is_populated_) 275 storage_.value_ = std::forward<U>(value); 276 else 277 storage_.Init(std::forward<U>(value)); 278 } 279 280 void FreeIfNeeded() { 281 if (!storage_.is_populated_) 282 return; 283 storage_.value_.~T(); 284 storage_.is_populated_ = false; 285 } 286 287 // For implementing conversion, allow access to other typed OptionalBase 288 // class. 289 template <typename U> 290 friend class OptionalBase; 291 292 OptionalStorage<T> storage_; 293 }; 294 295 // The following {Copy,Move}{Constructible,Assignable} structs are helpers to 296 // implement constructor/assign-operator overloading. Specifically, if T is 297 // is not movable but copyable, Optional<T>'s move constructor should not 298 // participate in overload resolution. This inheritance trick implements that. 299 template <bool is_copy_constructible> 300 struct CopyConstructible {}; 301 302 template <> 303 struct CopyConstructible<false> { 304 constexpr CopyConstructible() = default; 305 constexpr CopyConstructible(const CopyConstructible&) = delete; 306 constexpr CopyConstructible(CopyConstructible&&) = default; 307 CopyConstructible& operator=(const CopyConstructible&) = default; 308 CopyConstructible& operator=(CopyConstructible&&) = default; 309 }; 310 311 template <bool is_move_constructible> 312 struct MoveConstructible {}; 313 314 template <> 315 struct MoveConstructible<false> { 316 constexpr MoveConstructible() = default; 317 constexpr MoveConstructible(const MoveConstructible&) = default; 318 constexpr MoveConstructible(MoveConstructible&&) = delete; 319 MoveConstructible& operator=(const MoveConstructible&) = default; 320 MoveConstructible& operator=(MoveConstructible&&) = default; 321 }; 322 323 template <bool is_copy_assignable> 324 struct CopyAssignable {}; 325 326 template <> 327 struct CopyAssignable<false> { 328 constexpr CopyAssignable() = default; 329 constexpr CopyAssignable(const CopyAssignable&) = default; 330 constexpr CopyAssignable(CopyAssignable&&) = default; 331 CopyAssignable& operator=(const CopyAssignable&) = delete; 332 CopyAssignable& operator=(CopyAssignable&&) = default; 333 }; 334 335 template <bool is_move_assignable> 336 struct MoveAssignable {}; 337 338 template <> 339 struct MoveAssignable<false> { 340 constexpr MoveAssignable() = default; 341 constexpr MoveAssignable(const MoveAssignable&) = default; 342 constexpr MoveAssignable(MoveAssignable&&) = default; 343 MoveAssignable& operator=(const MoveAssignable&) = default; 344 MoveAssignable& operator=(MoveAssignable&&) = delete; 345 }; 346 347 // Helper to conditionally enable converting constructors and assign operators. 348 template <typename T, typename U> 349 struct IsConvertibleFromOptional 350 : std::integral_constant< 351 bool, 352 std::is_constructible<T, Optional<U>&>::value || 353 std::is_constructible<T, const Optional<U>&>::value || 354 std::is_constructible<T, Optional<U>&&>::value || 355 std::is_constructible<T, const Optional<U>&&>::value || 356 std::is_convertible<Optional<U>&, T>::value || 357 std::is_convertible<const Optional<U>&, T>::value || 358 std::is_convertible<Optional<U>&&, T>::value || 359 std::is_convertible<const Optional<U>&&, T>::value> {}; 360 361 template <typename T, typename U> 362 struct IsAssignableFromOptional 363 : std::integral_constant< 364 bool, 365 IsConvertibleFromOptional<T, U>::value || 366 std::is_assignable<T&, Optional<U>&>::value || 367 std::is_assignable<T&, const Optional<U>&>::value || 368 std::is_assignable<T&, Optional<U>&&>::value || 369 std::is_assignable<T&, const Optional<U>&&>::value> {}; 370 371 // Forward compatibility for C++17. 372 // Introduce one more deeper nested namespace to avoid leaking using std::swap. 373 namespace swappable_impl { 374 using std::swap; 375 376 struct IsSwappableImpl { 377 // Tests if swap can be called. Check<T&>(0) returns true_type iff swap 378 // is available for T. Otherwise, Check's overload resolution falls back 379 // to Check(...) declared below thanks to SFINAE, so returns false_type. 380 template <typename T> 381 static auto Check(int) 382 -> decltype(swap(std::declval<T>(), std::declval<T>()), std::true_type()); 383 384 template <typename T> 385 static std::false_type Check(...); 386 }; 387 } // namespace swappable_impl 388 389 template <typename T> 390 struct IsSwappable : decltype(swappable_impl::IsSwappableImpl::Check<T&>(0)) {}; 391 392 // Forward compatibility for C++20. 393 template <typename T> 394 using RemoveCvRefT = std::remove_cv_t<std::remove_reference_t<T>>; 395 396 } // namespace internal 397 398 // On Windows, by default, empty-base class optimization does not work, 399 // which means even if the base class is empty struct, it still consumes one 400 // byte for its body. __declspec(empty_bases) enables the optimization. 401 // cf) 402 // https://blogs.msdn.microsoft.com/vcblog/2016/03/30/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/ 403 #ifdef OS_WIN 404 #define OPTIONAL_DECLSPEC_EMPTY_BASES __declspec(empty_bases) 405 #else 406 #define OPTIONAL_DECLSPEC_EMPTY_BASES 407 #endif 408 409 // base::Optional is a Chromium version of the C++17 optional class: 410 // std::optional documentation: 411 // http://en.cppreference.com/w/cpp/utility/optional 412 // Chromium documentation: 413 // https://chromium.googlesource.com/chromium/src/+/master/docs/optional.md 414 // 415 // These are the differences between the specification and the implementation: 416 // - Constructors do not use 'constexpr' as it is a C++14 extension. 417 // - 'constexpr' might be missing in some places for reasons specified locally. 418 // - No exceptions are thrown, because they are banned from Chromium. 419 // Marked noexcept for only move constructor and move assign operators. 420 // - All the non-members are in the 'base' namespace instead of 'std'. 421 // 422 // Note that T cannot have a constructor T(Optional<T>) etc. Optional<T> checks 423 // T's constructor (specifically via IsConvertibleFromOptional), and in the 424 // check whether T can be constructible from Optional<T>, which is recursive 425 // so it does not work. As of Feb 2018, std::optional C++17 implementation in 426 // both clang and gcc has same limitation. MSVC SFINAE looks to have different 427 // behavior, but anyway it reports an error, too. 428 template <typename T> 429 class OPTIONAL_DECLSPEC_EMPTY_BASES Optional 430 : public internal::OptionalBase<T>, 431 public internal::CopyConstructible<std::is_copy_constructible<T>::value>, 432 public internal::MoveConstructible<std::is_move_constructible<T>::value>, 433 public internal::CopyAssignable<std::is_copy_constructible<T>::value && 434 std::is_copy_assignable<T>::value>, 435 public internal::MoveAssignable<std::is_move_constructible<T>::value && 436 std::is_move_assignable<T>::value> { 437 public: 438 #undef OPTIONAL_DECLSPEC_EMPTY_BASES 439 using value_type = T; 440 441 // Defer default/copy/move constructor implementation to OptionalBase. 442 constexpr Optional() = default; 443 constexpr Optional(const Optional& other) = default; 444 constexpr Optional(Optional&& other) noexcept( 445 std::is_nothrow_move_constructible<T>::value) = default; 446 447 constexpr Optional(nullopt_t) {} // NOLINT(runtime/explicit) 448 449 // Converting copy constructor. "explicit" only if 450 // std::is_convertible<const U&, T>::value is false. It is implemented by 451 // declaring two almost same constructors, but that condition in enable_if_t 452 // is different, so that either one is chosen, thanks to SFINAE. 453 template < 454 typename U, 455 std::enable_if_t<std::is_constructible<T, const U&>::value && 456 !internal::IsConvertibleFromOptional<T, U>::value && 457 std::is_convertible<const U&, T>::value, 458 bool> = false> 459 Optional(const Optional<U>& other) : internal::OptionalBase<T>(other) {} 460 461 template < 462 typename U, 463 std::enable_if_t<std::is_constructible<T, const U&>::value && 464 !internal::IsConvertibleFromOptional<T, U>::value && 465 !std::is_convertible<const U&, T>::value, 466 bool> = false> 467 explicit Optional(const Optional<U>& other) 468 : internal::OptionalBase<T>(other) {} 469 470 // Converting move constructor. Similar to converting copy constructor, 471 // declaring two (explicit and non-explicit) constructors. 472 template < 473 typename U, 474 std::enable_if_t<std::is_constructible<T, U&&>::value && 475 !internal::IsConvertibleFromOptional<T, U>::value && 476 std::is_convertible<U&&, T>::value, 477 bool> = false> 478 Optional(Optional<U>&& other) : internal::OptionalBase<T>(std::move(other)) {} 479 480 template < 481 typename U, 482 std::enable_if_t<std::is_constructible<T, U&&>::value && 483 !internal::IsConvertibleFromOptional<T, U>::value && 484 !std::is_convertible<U&&, T>::value, 485 bool> = false> 486 explicit Optional(Optional<U>&& other) 487 : internal::OptionalBase<T>(std::move(other)) {} 488 489 template <class... Args> 490 constexpr explicit Optional(in_place_t, Args&&... args) 491 : internal::OptionalBase<T>(in_place, std::forward<Args>(args)...) {} 492 493 template < 494 class U, 495 class... Args, 496 class = std::enable_if_t<std::is_constructible<value_type, 497 std::initializer_list<U>&, 498 Args...>::value>> 499 constexpr explicit Optional(in_place_t, 500 std::initializer_list<U> il, 501 Args&&... args) 502 : internal::OptionalBase<T>(in_place, il, std::forward<Args>(args)...) {} 503 504 // Forward value constructor. Similar to converting constructors, 505 // conditionally explicit. 506 template < 507 typename U = value_type, 508 std::enable_if_t< 509 std::is_constructible<T, U&&>::value && 510 !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value && 511 !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value && 512 std::is_convertible<U&&, T>::value, 513 bool> = false> 514 constexpr Optional(U&& value) 515 : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {} 516 517 template < 518 typename U = value_type, 519 std::enable_if_t< 520 std::is_constructible<T, U&&>::value && 521 !std::is_same<internal::RemoveCvRefT<U>, in_place_t>::value && 522 !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value && 523 !std::is_convertible<U&&, T>::value, 524 bool> = false> 525 constexpr explicit Optional(U&& value) 526 : internal::OptionalBase<T>(in_place, std::forward<U>(value)) {} 527 528 ~Optional() = default; 529 530 // Defer copy-/move- assign operator implementation to OptionalBase. 531 Optional& operator=(const Optional& other) = default; 532 Optional& operator=(Optional&& other) noexcept( 533 std::is_nothrow_move_assignable<T>::value&& 534 std::is_nothrow_move_constructible<T>::value) = default; 535 536 Optional& operator=(nullopt_t) { 537 FreeIfNeeded(); 538 return *this; 539 } 540 541 // Perfect-forwarded assignment. 542 template <typename U> 543 std::enable_if_t< 544 !std::is_same<internal::RemoveCvRefT<U>, Optional<T>>::value && 545 std::is_constructible<T, U>::value && 546 std::is_assignable<T&, U>::value && 547 (!std::is_scalar<T>::value || 548 !std::is_same<std::decay_t<U>, T>::value), 549 Optional&> 550 operator=(U&& value) { 551 InitOrAssign(std::forward<U>(value)); 552 return *this; 553 } 554 555 // Copy assign the state of other. 556 template <typename U> 557 std::enable_if_t<!internal::IsAssignableFromOptional<T, U>::value && 558 std::is_constructible<T, const U&>::value && 559 std::is_assignable<T&, const U&>::value, 560 Optional&> 561 operator=(const Optional<U>& other) { 562 CopyAssign(other); 563 return *this; 564 } 565 566 // Move assign the state of other. 567 template <typename U> 568 std::enable_if_t<!internal::IsAssignableFromOptional<T, U>::value && 569 std::is_constructible<T, U>::value && 570 std::is_assignable<T&, U>::value, 571 Optional&> 572 operator=(Optional<U>&& other) { 573 MoveAssign(std::move(other)); 574 return *this; 575 } 576 577 constexpr const T* operator->() const { 578 DCHECK(storage_.is_populated_); 579 return &storage_.value_; 580 } 581 582 constexpr T* operator->() { 583 DCHECK(storage_.is_populated_); 584 return &storage_.value_; 585 } 586 587 constexpr const T& operator*() const & { 588 DCHECK(storage_.is_populated_); 589 return storage_.value_; 590 } 591 592 constexpr T& operator*() & { 593 DCHECK(storage_.is_populated_); 594 return storage_.value_; 595 } 596 597 constexpr const T&& operator*() const && { 598 DCHECK(storage_.is_populated_); 599 return std::move(storage_.value_); 600 } 601 602 constexpr T&& operator*() && { 603 DCHECK(storage_.is_populated_); 604 return std::move(storage_.value_); 605 } 606 607 constexpr explicit operator bool() const { return storage_.is_populated_; } 608 609 constexpr bool has_value() const { return storage_.is_populated_; } 610 611 constexpr T& value() & { 612 CHECK(storage_.is_populated_); 613 return storage_.value_; 614 } 615 616 constexpr const T& value() const & { 617 CHECK(storage_.is_populated_); 618 return storage_.value_; 619 } 620 621 constexpr T&& value() && { 622 CHECK(storage_.is_populated_); 623 return std::move(storage_.value_); 624 } 625 626 constexpr const T&& value() const && { 627 CHECK(storage_.is_populated_); 628 return std::move(storage_.value_); 629 } 630 631 template <class U> 632 constexpr T value_or(U&& default_value) const& { 633 // TODO(mlamouri): add the following assert when possible: 634 // static_assert(std::is_copy_constructible<T>::value, 635 // "T must be copy constructible"); 636 static_assert(std::is_convertible<U, T>::value, 637 "U must be convertible to T"); 638 return storage_.is_populated_ 639 ? storage_.value_ 640 : static_cast<T>(std::forward<U>(default_value)); 641 } 642 643 template <class U> 644 constexpr T value_or(U&& default_value) && { 645 // TODO(mlamouri): add the following assert when possible: 646 // static_assert(std::is_move_constructible<T>::value, 647 // "T must be move constructible"); 648 static_assert(std::is_convertible<U, T>::value, 649 "U must be convertible to T"); 650 return storage_.is_populated_ 651 ? std::move(storage_.value_) 652 : static_cast<T>(std::forward<U>(default_value)); 653 } 654 655 void swap(Optional& other) { 656 if (!storage_.is_populated_ && !other.storage_.is_populated_) 657 return; 658 659 if (storage_.is_populated_ != other.storage_.is_populated_) { 660 if (storage_.is_populated_) { 661 other.storage_.Init(std::move(storage_.value_)); 662 FreeIfNeeded(); 663 } else { 664 storage_.Init(std::move(other.storage_.value_)); 665 other.FreeIfNeeded(); 666 } 667 return; 668 } 669 670 DCHECK(storage_.is_populated_ && other.storage_.is_populated_); 671 using std::swap; 672 swap(**this, *other); 673 } 674 675 void reset() { FreeIfNeeded(); } 676 677 template <class... Args> 678 T& emplace(Args&&... args) { 679 FreeIfNeeded(); 680 storage_.Init(std::forward<Args>(args)...); 681 return storage_.value_; 682 } 683 684 template <class U, class... Args> 685 std::enable_if_t< 686 std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value, 687 T&> 688 emplace(std::initializer_list<U> il, Args&&... args) { 689 FreeIfNeeded(); 690 storage_.Init(il, std::forward<Args>(args)...); 691 return storage_.value_; 692 } 693 694 private: 695 // Accessing template base class's protected member needs explicit 696 // declaration to do so. 697 using internal::OptionalBase<T>::CopyAssign; 698 using internal::OptionalBase<T>::FreeIfNeeded; 699 using internal::OptionalBase<T>::InitOrAssign; 700 using internal::OptionalBase<T>::MoveAssign; 701 using internal::OptionalBase<T>::storage_; 702 }; 703 704 // Here after defines comparation operators. The definition follows 705 // http://en.cppreference.com/w/cpp/utility/optional/operator_cmp 706 // while bool() casting is replaced by has_value() to meet the chromium 707 // style guide. 708 template <class T, class U> 709 constexpr bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) { 710 if (lhs.has_value() != rhs.has_value()) 711 return false; 712 if (!lhs.has_value()) 713 return true; 714 return *lhs == *rhs; 715 } 716 717 template <class T, class U> 718 constexpr bool operator!=(const Optional<T>& lhs, const Optional<U>& rhs) { 719 if (lhs.has_value() != rhs.has_value()) 720 return true; 721 if (!lhs.has_value()) 722 return false; 723 return *lhs != *rhs; 724 } 725 726 template <class T, class U> 727 constexpr bool operator<(const Optional<T>& lhs, const Optional<U>& rhs) { 728 if (!rhs.has_value()) 729 return false; 730 if (!lhs.has_value()) 731 return true; 732 return *lhs < *rhs; 733 } 734 735 template <class T, class U> 736 constexpr bool operator<=(const Optional<T>& lhs, const Optional<U>& rhs) { 737 if (!lhs.has_value()) 738 return true; 739 if (!rhs.has_value()) 740 return false; 741 return *lhs <= *rhs; 742 } 743 744 template <class T, class U> 745 constexpr bool operator>(const Optional<T>& lhs, const Optional<U>& rhs) { 746 if (!lhs.has_value()) 747 return false; 748 if (!rhs.has_value()) 749 return true; 750 return *lhs > *rhs; 751 } 752 753 template <class T, class U> 754 constexpr bool operator>=(const Optional<T>& lhs, const Optional<U>& rhs) { 755 if (!rhs.has_value()) 756 return true; 757 if (!lhs.has_value()) 758 return false; 759 return *lhs >= *rhs; 760 } 761 762 template <class T> 763 constexpr bool operator==(const Optional<T>& opt, nullopt_t) { 764 return !opt; 765 } 766 767 template <class T> 768 constexpr bool operator==(nullopt_t, const Optional<T>& opt) { 769 return !opt; 770 } 771 772 template <class T> 773 constexpr bool operator!=(const Optional<T>& opt, nullopt_t) { 774 return opt.has_value(); 775 } 776 777 template <class T> 778 constexpr bool operator!=(nullopt_t, const Optional<T>& opt) { 779 return opt.has_value(); 780 } 781 782 template <class T> 783 constexpr bool operator<(const Optional<T>& opt, nullopt_t) { 784 return false; 785 } 786 787 template <class T> 788 constexpr bool operator<(nullopt_t, const Optional<T>& opt) { 789 return opt.has_value(); 790 } 791 792 template <class T> 793 constexpr bool operator<=(const Optional<T>& opt, nullopt_t) { 794 return !opt; 795 } 796 797 template <class T> 798 constexpr bool operator<=(nullopt_t, const Optional<T>& opt) { 799 return true; 800 } 801 802 template <class T> 803 constexpr bool operator>(const Optional<T>& opt, nullopt_t) { 804 return opt.has_value(); 805 } 806 807 template <class T> 808 constexpr bool operator>(nullopt_t, const Optional<T>& opt) { 809 return false; 810 } 811 812 template <class T> 813 constexpr bool operator>=(const Optional<T>& opt, nullopt_t) { 814 return true; 815 } 816 817 template <class T> 818 constexpr bool operator>=(nullopt_t, const Optional<T>& opt) { 819 return !opt; 820 } 821 822 template <class T, class U> 823 constexpr bool operator==(const Optional<T>& opt, const U& value) { 824 return opt.has_value() ? *opt == value : false; 825 } 826 827 template <class T, class U> 828 constexpr bool operator==(const U& value, const Optional<T>& opt) { 829 return opt.has_value() ? value == *opt : false; 830 } 831 832 template <class T, class U> 833 constexpr bool operator!=(const Optional<T>& opt, const U& value) { 834 return opt.has_value() ? *opt != value : true; 835 } 836 837 template <class T, class U> 838 constexpr bool operator!=(const U& value, const Optional<T>& opt) { 839 return opt.has_value() ? value != *opt : true; 840 } 841 842 template <class T, class U> 843 constexpr bool operator<(const Optional<T>& opt, const U& value) { 844 return opt.has_value() ? *opt < value : true; 845 } 846 847 template <class T, class U> 848 constexpr bool operator<(const U& value, const Optional<T>& opt) { 849 return opt.has_value() ? value < *opt : false; 850 } 851 852 template <class T, class U> 853 constexpr bool operator<=(const Optional<T>& opt, const U& value) { 854 return opt.has_value() ? *opt <= value : true; 855 } 856 857 template <class T, class U> 858 constexpr bool operator<=(const U& value, const Optional<T>& opt) { 859 return opt.has_value() ? value <= *opt : false; 860 } 861 862 template <class T, class U> 863 constexpr bool operator>(const Optional<T>& opt, const U& value) { 864 return opt.has_value() ? *opt > value : false; 865 } 866 867 template <class T, class U> 868 constexpr bool operator>(const U& value, const Optional<T>& opt) { 869 return opt.has_value() ? value > *opt : true; 870 } 871 872 template <class T, class U> 873 constexpr bool operator>=(const Optional<T>& opt, const U& value) { 874 return opt.has_value() ? *opt >= value : false; 875 } 876 877 template <class T, class U> 878 constexpr bool operator>=(const U& value, const Optional<T>& opt) { 879 return opt.has_value() ? value >= *opt : true; 880 } 881 882 template <class T> 883 constexpr Optional<std::decay_t<T>> make_optional(T&& value) { 884 return Optional<std::decay_t<T>>(std::forward<T>(value)); 885 } 886 887 template <class T, class... Args> 888 constexpr Optional<T> make_optional(Args&&... args) { 889 return Optional<T>(in_place, std::forward<Args>(args)...); 890 } 891 892 template <class T, class U, class... Args> 893 constexpr Optional<T> make_optional(std::initializer_list<U> il, 894 Args&&... args) { 895 return Optional<T>(in_place, il, std::forward<Args>(args)...); 896 } 897 898 // Partial specialization for a function template is not allowed. Also, it is 899 // not allowed to add overload function to std namespace, while it is allowed 900 // to specialize the template in std. Thus, swap() (kind of) overloading is 901 // defined in base namespace, instead. 902 template <class T> 903 std::enable_if_t<std::is_move_constructible<T>::value && 904 internal::IsSwappable<T>::value> 905 swap(Optional<T>& lhs, Optional<T>& rhs) { 906 lhs.swap(rhs); 907 } 908 909 } // namespace base 910 911 namespace std { 912 913 template <class T> 914 struct hash<base::Optional<T>> { 915 size_t operator()(const base::Optional<T>& opt) const { 916 return opt == base::nullopt ? 0 : std::hash<T>()(*opt); 917 } 918 }; 919 920 } // namespace std 921 922 #endif // BASE_OPTIONAL_H_ 923