Chromium Code Reviews| Index: base/optional.h |
| diff --git a/base/optional.h b/base/optional.h |
| index b468964ae339fbead38f769dd315ff39a008d054..046b57acfad0941ebc84f11a1f00f855491cc4c1 100644 |
| --- a/base/optional.h |
| +++ b/base/optional.h |
| @@ -8,7 +8,6 @@ |
| #include <type_traits> |
| #include "base/logging.h" |
| -#include "base/memory/aligned_memory.h" |
| #include "base/template_util.h" |
| namespace base { |
| @@ -35,28 +34,32 @@ namespace internal { |
| template <typename T, bool = base::is_trivially_destructible<T>::value> |
| struct OptionalStorage { |
| + OptionalStorage() {}; |
| // When T is not trivially destructible we must call its |
| // destructor before deallocating its memory. |
| ~OptionalStorage() { |
| if (!is_null_) |
| - buffer_.template data_as<T>()->~T(); |
| + value_.~T(); |
| } |
| bool is_null_ = true; |
| - base::AlignedMemory<sizeof(T), ALIGNOF(T)> buffer_; |
| + union { |
| + T value_; |
|
danakj
2016/06/22 23:00:03
Why does libcxx put a second field in the union? h
kwiberg-chromium
2016/06/23 02:18:49
It seems like it's required to make constexpr cons
|
| + }; |
| }; |
| template <typename T> |
| struct OptionalStorage<T, true> { |
| - // When T is trivially destructible (i.e. its destructor does nothing) |
| - // there is no need to call it. |
| - // Since |base::AlignedMemory| is just an array its destructor |
| - // is trivial. Explicitly defaulting the destructor means it's not |
| - // user-provided. All of this together make this destructor trivial. |
| + OptionalStorage() {}; |
| + // When T is trivially destructible (i.e. its destructor does nothing) there |
| + // is no need to call it. Explicitly defaulting the destructor means it's not |
| + // user-provided. Those two together make this destructor trivial. |
| ~OptionalStorage() = default; |
| bool is_null_ = true; |
| - base::AlignedMemory<sizeof(T), ALIGNOF(T)> buffer_; |
| + union { |
| + T value_; |
| + }; |
| }; |
| } // namespace internal |
| @@ -167,26 +170,26 @@ class Optional { |
| // meant to be 'constexpr const'. |
| T& value() & { |
| DCHECK(!storage_.is_null_); |
| - return *storage_.buffer_.template data_as<T>(); |
| + return storage_.value_; |
| } |
| // TODO(mlamouri): can't use 'constexpr' with DCHECK. |
| const T& value() const& { |
| DCHECK(!storage_.is_null_); |
| - return *storage_.buffer_.template data_as<T>(); |
| + return storage_.value_; |
| } |
| // TODO(mlamouri): using 'constexpr' here breaks compiler that assume it was |
| // meant to be 'constexpr const'. |
| T&& value() && { |
| DCHECK(!storage_.is_null_); |
| - return std::move(*storage_.buffer_.template data_as<T>()); |
| + return std::move(storage_.value_); |
| } |
| // TODO(mlamouri): can't use 'constexpr' with DCHECK. |
| const T&& value() const&& { |
| DCHECK(!storage_.is_null_); |
| - return std::move(*storage_.buffer_.template data_as<T>()); |
| + return std::move(storage_.value_); |
| } |
| template <class U> |
| @@ -217,10 +220,10 @@ class Optional { |
| if (storage_.is_null_ != other.storage_.is_null_) { |
| if (storage_.is_null_) { |
| - Init(std::move(*other.storage_.buffer_.template data_as<T>())); |
| + Init(std::move(other.storage_.value_)); |
| other.FreeIfNeeded(); |
| } else { |
| - other.Init(std::move(*storage_.buffer_.template data_as<T>())); |
| + other.Init(std::move(storage_.value_)); |
| FreeIfNeeded(); |
| } |
| return; |
| @@ -240,20 +243,20 @@ class Optional { |
| private: |
| void Init(const T& value) { |
| DCHECK(storage_.is_null_); |
| - new (storage_.buffer_.void_data()) T(value); |
| + new (&storage_.value_) T(value); |
| storage_.is_null_ = false; |
| } |
| void Init(T&& value) { |
| DCHECK(storage_.is_null_); |
| - new (storage_.buffer_.void_data()) T(std::move(value)); |
| + new (&storage_.value_) T(std::move(value)); |
| storage_.is_null_ = false; |
| } |
| template <class... Args> |
| void Init(Args&&... args) { |
| DCHECK(storage_.is_null_); |
| - new (storage_.buffer_.void_data()) T(std::forward<Args>(args)...); |
| + new (&storage_.value_) T(std::forward<Args>(args)...); |
| storage_.is_null_ = false; |
| } |
| @@ -261,20 +264,20 @@ class Optional { |
| if (storage_.is_null_) |
| Init(value); |
| else |
| - *storage_.buffer_.template data_as<T>() = value; |
| + storage_.value_ = value; |
| } |
| void InitOrAssign(T&& value) { |
| if (storage_.is_null_) |
| Init(std::move(value)); |
| else |
| - *storage_.buffer_.template data_as<T>() = std::move(value); |
| + storage_.value_ = std::move(value); |
| } |
| void FreeIfNeeded() { |
| if (storage_.is_null_) |
| return; |
| - storage_.buffer_.template data_as<T>()->~T(); |
| + storage_.value_.~T(); |
| storage_.is_null_ = true; |
| } |