summaryrefslogtreecommitdiff
path: root/base/optional.h
diff options
context:
space:
mode:
authorHidehiko Abe <hidehiko@chromium.org>2018-01-20 08:50:24 +0900
committerQijiang Fan <fqj@google.com>2020-06-05 08:17:58 +0900
commit3d6a7ef14c3ad79bebed6020ee30535d0c110586 (patch)
tree0c73326456eddfe972371f174a80537813ba3c42 /base/optional.h
parentc6b639035cb30b39d382491014d1a74a003eace9 (diff)
downloadlibchrome-3d6a7ef14c3ad79bebed6020ee30535d0c110586.tar.gz
Fix non-copyable class's optional move.
BUG=784732 TEST=Ran base_unittests -gtest_filter=*Optional* Change-Id: Ibb5d7cc5d62deacdba7f811f5a7b83c1c58c3907 Reviewed-on: https://chromium-review.googlesource.com/855976 Reviewed-by: danakj <danakj@chromium.org> Commit-Queue: Hidehiko Abe <hidehiko@chromium.org> Cr-Commit-Position: refs/heads/master@{#530663} CrOS-Libchrome-Original-Commit: f1c8789c71dbdaeeef98ecd52c9715495824e6b0
Diffstat (limited to 'base/optional.h')
-rw-r--r--base/optional.h24
1 files changed, 21 insertions, 3 deletions
diff --git a/base/optional.h b/base/optional.h
index f6619a5758..34e36fabeb 100644
--- a/base/optional.h
+++ b/base/optional.h
@@ -44,6 +44,15 @@ struct OptionalStorageBase {
// When T is not trivially destructible we must call its
// destructor before deallocating its memory.
+ // Note that this hides the (implicitly declared) move constructor, which
+ // would be used for constexpr move constructor in OptionalStorage<T>.
+ // It is needed iff T is trivially move constructible. However, the current
+ // is_trivially_{copy,move}_constructible implementation requires
+ // is_trivially_destructible (which looks a bug, cf:
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452 and
+ // http://cplusplus.github.io/LWG/lwg-active.html#2116), so it is not
+ // necessary for this case at the moment. Please see also the destructor
+ // comment in "is_trivially_destructible = true" specialization below.
~OptionalStorageBase() {
if (!is_null_)
value_.~T();
@@ -77,9 +86,18 @@ struct OptionalStorageBase<T, true /* trivially destructible */> {
: is_null_(false), value_(std::forward<Args>(args)...) {}
// 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.
- ~OptionalStorageBase() = default;
+ // is no need to call it. Implicitly defined destructor is trivial, because
+ // both members (bool and union containing only variants which are trivially
+ // destructible) are trivially destructible.
+ // Explicitly-defaulted destructor is also trivial, but do not use it here,
+ // because it hides the implicit move constructor. It is needed to implement
+ // constexpr move constructor in OptionalStorage iff T is trivially move
+ // constructible. Note that, if T is trivially move constructible, the move
+ // constructor of OptionalStorageBase<T> is also implicitly defined and it is
+ // trivially move constructor. If T is not trivially move constructible,
+ // "not declaring move constructor without destructor declaration" here means
+ // "delete move constructor", which works because any move constructor of
+ // OptionalStorage will not refer to it in that case.
template <class... Args>
void Init(Args&&... args) {