Index: base/optional.h |
diff --git a/base/optional.h b/base/optional.h |
index 98cd95857094023fae865137d7b90838a93d986f..3adda97c0217ee5c05d8c07a0fbaab062714d03a 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,40 @@ 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 { |
+ // |empty_| exists so that the union will always be initialized, even when |
+ // it doesn't contain a value. Not initializing it has been observed to |
+ // trigger comiler warnings. |
+ char empty_ = '\0'; |
+ T value_; |
+ }; |
}; |
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 { |
+ // |empty_| exists so that the union will always be initialized, even when |
+ // it doesn't contain a value. Not initializing it has been observed to |
+ // trigger comiler warnings. |
+ char empty_ = '\0'; |
+ T value_; |
+ }; |
}; |
} // namespace internal |
@@ -169,26 +180,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> |
@@ -219,10 +230,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; |
@@ -246,20 +257,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; |
} |
@@ -267,20 +278,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; |
} |