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; |
} |