diff --git a/AK/Optional.h b/AK/Optional.h index 1bb6441bcb..7519072a8a 100644 --- a/AK/Optional.h +++ b/AK/Optional.h @@ -446,16 +446,22 @@ public: return *this; } - // Note: Disallows assignment from a temporary as this does not do any lifetime extension. template requires(!IsSame>) - ALWAYS_INLINE Optional& operator=(U&& value) - requires(CanBePlacedInOptional && IsLvalueReference) + ALWAYS_INLINE Optional& operator=(U& value) + requires(CanBePlacedInOptional) { m_pointer = &value; return *this; } + // Note: Disallows assignment from a temporary as this does not do any lifetime extension. + template + requires(!IsSame>) + ALWAYS_INLINE consteval Optional& operator=(RemoveReference const&& value) + requires(CanBePlacedInOptional) + = delete; + ALWAYS_INLINE void clear() { m_pointer = nullptr; diff --git a/Tests/AK/TestOptional.cpp b/Tests/AK/TestOptional.cpp index cb17d62deb..2c0f3f49a5 100644 --- a/Tests/AK/TestOptional.cpp +++ b/Tests/AK/TestOptional.cpp @@ -272,6 +272,34 @@ TEST_CASE(comparison_reference) EXPECT_NE(opt1, opt3); } +template +struct CheckAssignments; + +template +requires(requires { declval() = declval(); }) +struct CheckAssignments { + static constexpr bool allowed = true; +}; + +template +requires(!requires { declval() = declval(); }) +struct CheckAssignments { + static constexpr bool allowed = false; +}; + +static_assert(CheckAssignments, int>::allowed); +static_assert(!CheckAssignments, double*>::allowed); + +static_assert(CheckAssignments, int&>::allowed); +static_assert(!CheckAssignments, int const&>::allowed); +static_assert(!CheckAssignments, int&&>::allowed); +static_assert(!CheckAssignments, int const&&>::allowed); + +static_assert(CheckAssignments, int&>::allowed); +static_assert(CheckAssignments, int const&>::allowed); +static_assert(CheckAssignments, int&&>::allowed); // Lifetime extension +static_assert(CheckAssignments, int const&&>::allowed); // Lifetime extension + TEST_CASE(string_specialization) { EXPECT_EQ(sizeof(Optional), sizeof(String));