Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(173)

Unified Diff: base/optional.h

Issue 2080003002: base::Optional: Use anonymous union instead of base::AlignedMemory (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: review nits Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | docs/optional.md » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
}
« no previous file with comments | « no previous file | docs/optional.md » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698