diff --git a/AK/Optional.h b/AK/Optional.h index a5f1c51540..2620498fe7 100644 --- a/AK/Optional.h +++ b/AK/Optional.h @@ -9,11 +9,30 @@ #include #include +#include #include #include namespace AK { +namespace Detail { +template +struct ConditionallyResultType; + +template +struct ConditionallyResultType { + using Type = typename T::ResultType; +}; + +template +struct ConditionallyResultType { + using Type = T; +}; +} + +template +using ConditionallyResultType = typename Detail::ConditionallyResultType::Type; + // NOTE: If you're here because of an internal compiler error in GCC 10.3.0+, // it's because of the following bug: // @@ -214,6 +233,36 @@ public: ALWAYS_INLINE T const* operator->() const { return &value(); } ALWAYS_INLINE T* operator->() { return &value(); } + template()(declval())), auto IsErrorOr = IsSpecializationOf, typename OptionalType = Optional>> + ALWAYS_INLINE Conditional, OptionalType> map(F&& mapper) + { + if constexpr (IsErrorOr) { + if (m_has_value) + return OptionalType { TRY(mapper(value())) }; + return OptionalType {}; + } else { + if (m_has_value) + return OptionalType { mapper(value()) }; + + return OptionalType {}; + } + } + + template()(declval())), auto IsErrorOr = IsSpecializationOf, typename OptionalType = Optional>> + ALWAYS_INLINE Conditional, OptionalType> map(F&& mapper) const + { + if constexpr (IsErrorOr) { + if (m_has_value) + return OptionalType { TRY(mapper(value())) }; + return OptionalType {}; + } else { + if (m_has_value) + return OptionalType { mapper(value()) }; + + return OptionalType {}; + } + } + private: alignas(T) u8 m_storage[sizeof(T)]; bool m_has_value { false }; @@ -375,6 +424,36 @@ public: return {}; } + template()(declval())), auto IsErrorOr = IsSpecializationOf, typename OptionalType = Optional>> + ALWAYS_INLINE Conditional, OptionalType> map(F&& mapper) + { + if constexpr (IsErrorOr) { + if (m_pointer != nullptr) + return OptionalType { TRY(mapper(value())) }; + return OptionalType {}; + } else { + if (m_pointer != nullptr) + return OptionalType { mapper(value()) }; + + return OptionalType {}; + } + } + + template()(declval())), auto IsErrorOr = IsSpecializationOf, typename OptionalType = Optional>> + ALWAYS_INLINE Conditional, OptionalType> map(F&& mapper) const + { + if constexpr (IsErrorOr) { + if (m_pointer != nullptr) + return OptionalType { TRY(mapper(value())) }; + return OptionalType {}; + } else { + if (m_pointer != nullptr) + return OptionalType { mapper(value()) }; + + return OptionalType {}; + } + } + private: RemoveReference* m_pointer { nullptr }; };