Browse Source

AK: Make Optional<T> explicitly constructible from Optional<U>

As long as T is constructible from U. This allows us to avoid patterns
like `abc.has_value() ? Optional<U>(abc.value()) : Optional<U>()`.
Idan Horowitz 3 years ago
parent
commit
a3a4d0aea2
1 changed files with 21 additions and 4 deletions
  1. 21 4
      AK/Optional.h

+ 21 - 4
AK/Optional.h

@@ -24,6 +24,9 @@ namespace AK {
 
 template<typename T>
 class [[nodiscard]] Optional {
+    template<typename U>
+    friend class Optional;
+
 public:
     using ValueType = T;
 
@@ -50,17 +53,31 @@ public:
 #endif
         : m_has_value(other.m_has_value)
     {
-        if (other.has_value()) {
+        if (other.has_value())
             new (&m_storage) T(other.value());
-        }
     }
 
     ALWAYS_INLINE Optional(Optional&& other)
         : m_has_value(other.m_has_value)
     {
-        if (other.has_value()) {
+        if (other.has_value())
+            new (&m_storage) T(other.release_value());
+    }
+
+    template<typename U>
+    requires(IsConstructible<T, U const&> && !IsSpecializationOf<T, Optional> && !IsSpecializationOf<U, Optional>) ALWAYS_INLINE explicit Optional(Optional<U> const& other)
+        : m_has_value(other.m_has_value)
+    {
+        if (other.has_value())
+            new (&m_storage) T(other.value());
+    }
+
+    template<typename U>
+    requires(IsConstructible<T, U&&> && !IsSpecializationOf<T, Optional> && !IsSpecializationOf<U, Optional>) ALWAYS_INLINE explicit Optional(Optional<U>&& other)
+        : m_has_value(other.m_has_value)
+    {
+        if (other.has_value())
             new (&m_storage) T(other.release_value());
-        }
     }
 
     template<typename U = T>