| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_OPTIONAL_H_ | 5 #ifndef BASE_OPTIONAL_H_ |
| 6 #define BASE_OPTIONAL_H_ | 6 #define BASE_OPTIONAL_H_ |
| 7 | 7 |
| 8 #include <type_traits> | 8 #include <type_traits> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 constexpr in_place_t in_place = {}; | 27 constexpr in_place_t in_place = {}; |
| 28 | 28 |
| 29 // Specification: | 29 // Specification: |
| 30 // http://en.cppreference.com/w/cpp/utility/optional/nullopt | 30 // http://en.cppreference.com/w/cpp/utility/optional/nullopt |
| 31 constexpr nullopt_t nullopt(0); | 31 constexpr nullopt_t nullopt(0); |
| 32 | 32 |
| 33 namespace internal { | 33 namespace internal { |
| 34 | 34 |
| 35 template <typename T, bool = base::is_trivially_destructible<T>::value> | 35 template <typename T, bool = base::is_trivially_destructible<T>::value> |
| 36 struct OptionalStorage { | 36 struct OptionalStorage { |
| 37 OptionalStorage() {} | 37 constexpr OptionalStorage() {} |
| 38 |
| 39 constexpr explicit OptionalStorage(const T& value) |
| 40 : is_null_(false), value_(value) {} |
| 41 |
| 42 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. |
| 43 explicit OptionalStorage(T&& value) |
| 44 : is_null_(false), value_(std::move(value)) {} |
| 45 |
| 46 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. |
| 47 template <class... Args> |
| 48 explicit OptionalStorage(base::in_place_t, Args&&... args) |
| 49 : is_null_(false), value_(std::forward<Args>(args)...) {} |
| 50 |
| 38 // When T is not trivially destructible we must call its | 51 // When T is not trivially destructible we must call its |
| 39 // destructor before deallocating its memory. | 52 // destructor before deallocating its memory. |
| 40 ~OptionalStorage() { | 53 ~OptionalStorage() { |
| 41 if (!is_null_) | 54 if (!is_null_) |
| 42 value_.~T(); | 55 value_.~T(); |
| 43 } | 56 } |
| 44 | 57 |
| 45 bool is_null_ = true; | 58 bool is_null_ = true; |
| 46 union { | 59 union { |
| 47 // |empty_| exists so that the union will always be initialized, even when | 60 // |empty_| exists so that the union will always be initialized, even when |
| 48 // it doesn't contain a value. Not initializing it has been observed to | 61 // it doesn't contain a value. Not initializing it has been observed to |
| 49 // trigger comiler warnings. | 62 // trigger comiler warnings. |
| 50 char empty_ = '\0'; | 63 char empty_ = '\0'; |
| 51 T value_; | 64 T value_; |
| 52 }; | 65 }; |
| 53 }; | 66 }; |
| 54 | 67 |
| 55 template <typename T> | 68 template <typename T> |
| 56 struct OptionalStorage<T, true> { | 69 struct OptionalStorage<T, true> { |
| 57 OptionalStorage() {} | 70 constexpr OptionalStorage() {} |
| 71 |
| 72 constexpr explicit OptionalStorage(const T& value) |
| 73 : is_null_(false), value_(value) {} |
| 74 |
| 75 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. |
| 76 explicit OptionalStorage(T&& value) |
| 77 : is_null_(false), value_(std::move(value)) {} |
| 78 |
| 79 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. |
| 80 template <class... Args> |
| 81 explicit OptionalStorage(base::in_place_t, Args&&... args) |
| 82 : is_null_(false), value_(std::forward<Args>(args)...) {} |
| 83 |
| 58 // When T is trivially destructible (i.e. its destructor does nothing) there | 84 // When T is trivially destructible (i.e. its destructor does nothing) there |
| 59 // is no need to call it. Explicitly defaulting the destructor means it's not | 85 // is no need to call it. Explicitly defaulting the destructor means it's not |
| 60 // user-provided. Those two together make this destructor trivial. | 86 // user-provided. Those two together make this destructor trivial. |
| 61 ~OptionalStorage() = default; | 87 ~OptionalStorage() = default; |
| 62 | 88 |
| 63 bool is_null_ = true; | 89 bool is_null_ = true; |
| 64 union { | 90 union { |
| 65 // |empty_| exists so that the union will always be initialized, even when | 91 // |empty_| exists so that the union will always be initialized, even when |
| 66 // it doesn't contain a value. Not initializing it has been observed to | 92 // it doesn't contain a value. Not initializing it has been observed to |
| 67 // trigger comiler warnings. | 93 // trigger comiler warnings. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 84 // - Constructors do not use 'constexpr' as it is a C++14 extension. | 110 // - Constructors do not use 'constexpr' as it is a C++14 extension. |
| 85 // - 'constexpr' might be missing in some places for reasons specified locally. | 111 // - 'constexpr' might be missing in some places for reasons specified locally. |
| 86 // - No exceptions are thrown, because they are banned from Chromium. | 112 // - No exceptions are thrown, because they are banned from Chromium. |
| 87 // - All the non-members are in the 'base' namespace instead of 'std'. | 113 // - All the non-members are in the 'base' namespace instead of 'std'. |
| 88 template <typename T> | 114 template <typename T> |
| 89 class Optional { | 115 class Optional { |
| 90 public: | 116 public: |
| 91 using value_type = T; | 117 using value_type = T; |
| 92 | 118 |
| 93 constexpr Optional() = default; | 119 constexpr Optional() = default; |
| 94 Optional(base::nullopt_t) : Optional() {} | 120 |
| 121 constexpr Optional(base::nullopt_t) {} |
| 95 | 122 |
| 96 Optional(const Optional& other) { | 123 Optional(const Optional& other) { |
| 97 if (!other.storage_.is_null_) | 124 if (!other.storage_.is_null_) |
| 98 Init(other.value()); | 125 Init(other.value()); |
| 99 } | 126 } |
| 100 | 127 |
| 101 Optional(Optional&& other) { | 128 Optional(Optional&& other) { |
| 102 if (!other.storage_.is_null_) | 129 if (!other.storage_.is_null_) |
| 103 Init(std::move(other.value())); | 130 Init(std::move(other.value())); |
| 104 } | 131 } |
| 105 | 132 |
| 106 Optional(const T& value) { Init(value); } | 133 constexpr Optional(const T& value) : storage_(value) {} |
| 107 | 134 |
| 108 Optional(T&& value) { Init(std::move(value)); } | 135 // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. |
| 136 Optional(T&& value) : storage_(std::move(value)) {} |
| 109 | 137 |
| 138 // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. |
| 110 template <class... Args> | 139 template <class... Args> |
| 111 explicit Optional(base::in_place_t, Args&&... args) { | 140 explicit Optional(base::in_place_t, Args&&... args) |
| 112 emplace(std::forward<Args>(args)...); | 141 : storage_(base::in_place, std::forward<Args>(args)...) {} |
| 113 } | |
| 114 | 142 |
| 115 ~Optional() = default; | 143 ~Optional() = default; |
| 116 | 144 |
| 117 Optional& operator=(base::nullopt_t) { | 145 Optional& operator=(base::nullopt_t) { |
| 118 FreeIfNeeded(); | 146 FreeIfNeeded(); |
| 119 return *this; | 147 return *this; |
| 120 } | 148 } |
| 121 | 149 |
| 122 Optional& operator=(const Optional& other) { | 150 Optional& operator=(const Optional& other) { |
| 123 if (other.storage_.is_null_) { | 151 if (other.storage_.is_null_) { |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 template <class T> | 493 template <class T> |
| 466 struct hash<base::Optional<T>> { | 494 struct hash<base::Optional<T>> { |
| 467 size_t operator()(const base::Optional<T>& opt) const { | 495 size_t operator()(const base::Optional<T>& opt) const { |
| 468 return opt == base::nullopt ? 0 : std::hash<T>()(*opt); | 496 return opt == base::nullopt ? 0 : std::hash<T>()(*opt); |
| 469 } | 497 } |
| 470 }; | 498 }; |
| 471 | 499 |
| 472 } // namespace std | 500 } // namespace std |
| 473 | 501 |
| 474 #endif // BASE_OPTIONAL_H_ | 502 #endif // BASE_OPTIONAL_H_ |
| OLD | NEW |