tpopela / rpms / chromium

Forked from rpms/chromium 6 years ago
Clone

Blame chromium-65.0.3325.146-Implement-converting-constructors-from-Optional-U.patch

4e6c6ef
diff -up chromium-65.0.3325.146/base/optional.h.converting chromium-65.0.3325.146/base/optional.h
4e6c6ef
--- chromium-65.0.3325.146/base/optional.h.converting	2018-03-13 22:31:05.248797490 -0400
4e6c6ef
+++ chromium-65.0.3325.146/base/optional.h	2018-03-13 22:33:10.826368771 -0400
4e6c6ef
@@ -31,6 +31,10 @@ constexpr in_place_t in_place = {};
4e6c6ef
 // http://en.cppreference.com/w/cpp/utility/optional/nullopt
4e6c6ef
 constexpr nullopt_t nullopt(0);
4e6c6ef
 
4e6c6ef
+// Forward declaration, which is refered by following helpers.
4e6c6ef
+template <typename T>
4e6c6ef
+class Optional;
4e6c6ef
+
4e6c6ef
 namespace internal {
4e6c6ef
 
4e6c6ef
 template <typename T, bool = std::is_trivially_destructible<T>::value>
4e6c6ef
@@ -220,6 +224,19 @@ class OptionalBase {
4e6c6ef
   constexpr explicit OptionalBase(in_place_t, Args&&... args)
4e6c6ef
       : storage_(in_place, std::forward<Args>(args)...) {}
4e6c6ef
 
4e6c6ef
+  // Implementation of converting constructors.
4e6c6ef
+  template <typename U>
4e6c6ef
+  explicit OptionalBase(const OptionalBase<U>& other) {
4e6c6ef
+    if (other.storage_.is_populated_)
4e6c6ef
+      storage_.Init(other.storage_.value_);
4e6c6ef
+  }
4e6c6ef
+
4e6c6ef
+  template <typename U>
4e6c6ef
+  explicit OptionalBase(OptionalBase<U>&& other) {
4e6c6ef
+    if (other.storage_.is_populated_)
4e6c6ef
+      storage_.Init(std::move(other.storage_.value_));
4e6c6ef
+  }
4e6c6ef
+
4e6c6ef
   ~OptionalBase() = default;
4e6c6ef
 
4e6c6ef
   OptionalBase& operator=(const OptionalBase& other) {
4e6c6ef
@@ -263,6 +280,11 @@ class OptionalBase {
4e6c6ef
     storage_.is_populated_ = false;
4e6c6ef
   }
4e6c6ef
 
4e6c6ef
+  // For implementing conversion, allow access to other typed OptionalBase
4e6c6ef
+  // class.
4e6c6ef
+  template <typename U>
4e6c6ef
+  friend class OptionalBase;
4e6c6ef
+
4e6c6ef
   OptionalStorage<T> storage_;
4e6c6ef
 };
4e6c6ef
 
4e6c6ef
@@ -318,6 +340,20 @@ struct MoveAssignable<false> {
4e6c6ef
   MoveAssignable& operator=(MoveAssignable&&) = delete;
4e6c6ef
 };
4e6c6ef
 
4e6c6ef
+// Helper to conditionally enable converting constructors.
4e6c6ef
+template <typename T, typename U>
4e6c6ef
+struct IsConvertibleFromOptional
4e6c6ef
+    : std::integral_constant<
4e6c6ef
+          bool,
4e6c6ef
+          std::is_constructible<T, Optional<U>&>::value ||
4e6c6ef
+              std::is_constructible<T, const Optional<U>&>::value ||
4e6c6ef
+              std::is_constructible<T, Optional<U>&&>::value ||
4e6c6ef
+              std::is_constructible<T, const Optional<U>&&>::value ||
4e6c6ef
+              std::is_convertible<Optional<U>&, T>::value ||
4e6c6ef
+              std::is_convertible<const Optional<U>&, T>::value ||
4e6c6ef
+              std::is_convertible<Optional<U>&&, T>::value ||
4e6c6ef
+              std::is_convertible<const Optional<U>&&, T>::value> {};
4e6c6ef
+
4e6c6ef
 }  // namespace internal
4e6c6ef
 
4e6c6ef
 // base::Optional is a Chromium version of the C++17 optional class:
4e6c6ef
@@ -348,7 +384,47 @@ class Optional
4e6c6ef
   constexpr Optional(const Optional& other) = default;
4e6c6ef
   constexpr Optional(Optional&& other) = default;
4e6c6ef
 
4e6c6ef
-  constexpr Optional(nullopt_t) {}
4e6c6ef
+  constexpr Optional(nullopt_t) {}  // NOLINT(runtime/explicit)
4e6c6ef
+
4e6c6ef
+  // Converting copy constructor. "explicit" only if
4e6c6ef
+  // std::is_convertible<const U&, T>::value is false. It is implemented by
4e6c6ef
+  // declaring two almost same constructors, but that condition in enable_if_t
4e6c6ef
+  // is different, so that either one is chosen, thanks to SFINAE.
4e6c6ef
+  template <
4e6c6ef
+      typename U,
4e6c6ef
+      std::enable_if_t<std::is_constructible<T, const U&>::value &&
4e6c6ef
+                           !internal::IsConvertibleFromOptional<T, U>::value &&
4e6c6ef
+                           std::is_convertible<const U&, T>::value,
4e6c6ef
+                       bool> = false>
4e6c6ef
+  Optional(const Optional<U>& other) : internal::OptionalBase<T>(other) {}
4e6c6ef
+
4e6c6ef
+  template <
4e6c6ef
+      typename U,
4e6c6ef
+      std::enable_if_t<std::is_constructible<T, const U&>::value &&
4e6c6ef
+                           !internal::IsConvertibleFromOptional<T, U>::value &&
4e6c6ef
+                           !std::is_convertible<const U&, T>::value,
4e6c6ef
+                       bool> = false>
4e6c6ef
+  explicit Optional(const Optional<U>& other)
4e6c6ef
+      : internal::OptionalBase<T>(other) {}
4e6c6ef
+
4e6c6ef
+  // Converting move constructor. Similar to converting copy constructor,
4e6c6ef
+  // declaring two (explicit and non-explicit) constructors.
4e6c6ef
+  template <
4e6c6ef
+      typename U,
4e6c6ef
+      std::enable_if_t<std::is_constructible<T, U&&>::value &&
4e6c6ef
+                           !internal::IsConvertibleFromOptional<T, U>::value &&
4e6c6ef
+                           std::is_convertible<U&&, T>::value,
4e6c6ef
+                       bool> = false>
4e6c6ef
+  Optional(Optional<U>&& other) : internal::OptionalBase<T>(std::move(other)) {}
4e6c6ef
+
4e6c6ef
+  template <
4e6c6ef
+      typename U,
4e6c6ef
+      std::enable_if_t<std::is_constructible<T, U&&>::value &&
4e6c6ef
+                           !internal::IsConvertibleFromOptional<T, U>::value &&
4e6c6ef
+                           !std::is_convertible<U&&, T>::value,
4e6c6ef
+                       bool> = false>
4e6c6ef
+  explicit Optional(Optional<U>&& other)
4e6c6ef
+      : internal::OptionalBase<T>(std::move(other)) {}
4e6c6ef
 
4e6c6ef
   constexpr Optional(const T& value)
4e6c6ef
       : internal::OptionalBase<T>(in_place, value) {}