diff -up chromium-65.0.3325.146/base/optional.h.ncnm chromium-65.0.3325.146/base/optional.h --- chromium-65.0.3325.146/base/optional.h.ncnm 2018-03-13 22:40:11.743226276 -0400 +++ chromium-65.0.3325.146/base/optional.h 2018-03-13 22:44:30.948211358 -0400 @@ -240,37 +240,37 @@ class OptionalBase { ~OptionalBase() = default; OptionalBase& operator=(const OptionalBase& other) { - if (!other.storage_.is_populated_) { - FreeIfNeeded(); - return *this; - } - - InitOrAssign(other.storage_.value_); + CopyAssign(other); return *this; } OptionalBase& operator=(OptionalBase&& other) { - if (!other.storage_.is_populated_) { - FreeIfNeeded(); - return *this; - } - - InitOrAssign(std::move(other.storage_.value_)); + MoveAssign(std::move(other)); return *this; } - void InitOrAssign(const T& value) { - if (!storage_.is_populated_) - storage_.Init(value); + template + void CopyAssign(const OptionalBase& other) { + if (other.storage_.is_populated_) + InitOrAssign(other.storage_.value_); else - storage_.value_ = value; + FreeIfNeeded(); } - void InitOrAssign(T&& value) { - if (!storage_.is_populated_) - storage_.Init(std::move(value)); + template + void MoveAssign(OptionalBase&& other) { + if (other.storage_.is_populated_) + InitOrAssign(std::move(other.storage_.value_)); + else + FreeIfNeeded(); + } + + template + void InitOrAssign(U&& value) { + if (storage_.is_populated_) + storage_.value_ = std::forward(value); else - storage_.value_ = std::move(value); + storage_.Init(std::forward(value)); } void FreeIfNeeded() { @@ -340,7 +340,7 @@ struct MoveAssignable { MoveAssignable& operator=(MoveAssignable&&) = delete; }; -// Helper to conditionally enable converting constructors. +// Helper to conditionally enable converting constructors and assign operators. template struct IsConvertibleFromOptional : std::integral_constant< @@ -354,6 +354,16 @@ struct IsConvertibleFromOptional std::is_convertible&&, T>::value || std::is_convertible&&, T>::value> {}; +template +struct IsAssignableFromOptional + : std::integral_constant< + bool, + IsConvertibleFromOptional::value || + std::is_assignable&>::value || + std::is_assignable&>::value || + std::is_assignable&&>::value || + std::is_assignable&&>::value> {}; + // Forward compatibility for C++20. template using RemoveCvRefT = std::remove_cv_t>; @@ -487,14 +497,42 @@ class Optional return *this; } - template - typename std::enable_if, T>::value, - Optional&>::type + // Perfect-forwarded assignment. + template + std::enable_if_t< + !std::is_same, Optional>::value && + std::is_constructible::value && + std::is_assignable::value && + (!std::is_scalar::value || + !std::is_same, T>::value), + Optional&> operator=(U&& value) { InitOrAssign(std::forward(value)); return *this; } +// Copy assign the state of other. + template + std::enable_if_t::value && + std::is_constructible::value && + std::is_assignable::value, + Optional&> + operator=(const Optional& other) { + CopyAssign(other); + return *this; + } + + // Move assign the state of other. + template + std::enable_if_t::value && + std::is_constructible::value && + std::is_assignable::value, + Optional&> + operator=(Optional&& other) { + MoveAssign(std::move(other)); + return *this; + } + constexpr const T* operator->() const { DCHECK(storage_.is_populated_); return &value(); @@ -606,8 +644,10 @@ class Optional private: // Accessing template base class's protected member needs explicit // declaration to do so. + using internal::OptionalBase::CopyAssign; using internal::OptionalBase::FreeIfNeeded; using internal::OptionalBase::InitOrAssign; + using internal::OptionalBase::MoveAssign; using internal::OptionalBase::storage_; };