1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 12:07:45 +00:00

AK+Kernel: Fix perfect forwarding constructors shadowing others

If a non-const lvalue reference is passed to these constructors, the
converting constructor will be selected instead of the desired copy/move
constructor.

Since I needed to touch `KResultOr` anyway, I made the forwarding
converting constructor use `forward<U>` instead of `move`. This meant
that previously, if a lvalue was passed to it, a move operation took
place even if no `move()` was called on it. Member initializers and
if-else statements have been changed to match our current coding style.
This commit is contained in:
Daniel Bertalan 2021-07-05 18:23:45 +02:00 committed by Gunnar Beutner
parent a2e0291172
commit 62f84e94c8
2 changed files with 16 additions and 10 deletions

View file

@ -62,13 +62,13 @@ public:
} }
template<typename CallableType> template<typename CallableType>
Function(CallableType&& callable) requires((IsFunctionObject<CallableType> && IsCallableWithArguments<CallableType, In...>)) Function(CallableType&& callable) requires((IsFunctionObject<CallableType> && IsCallableWithArguments<CallableType, In...> && !IsSame<RemoveCVReference<CallableType>, Function>))
{ {
init_with_callable(forward<CallableType>(callable)); init_with_callable(forward<CallableType>(callable));
} }
template<typename FunctionType> template<typename FunctionType>
Function(FunctionType f) requires((IsFunctionPointer<FunctionType> && IsCallableWithArguments<RemovePointer<FunctionType>, In...>)) Function(FunctionType f) requires((IsFunctionPointer<FunctionType> && IsCallableWithArguments<RemovePointer<FunctionType>, In...> && !IsSame<RemoveCVReference<FunctionType>, Function>))
{ {
init_with_callable(move(f)); init_with_callable(move(f));
} }

View file

@ -58,24 +58,30 @@ public:
} }
ALWAYS_INLINE KResultOr(T&& value) ALWAYS_INLINE KResultOr(T&& value)
: m_have_storage(true)
{ {
new (&m_storage) T(move(value)); new (&m_storage) T(move(value));
m_have_storage = true; }
ALWAYS_INLINE KResultOr(const T& value)
: m_have_storage(true)
{
new (&m_storage) T(value);
} }
template<typename U> template<typename U>
ALWAYS_INLINE KResultOr(U&& value) ALWAYS_INLINE KResultOr(U&& value) requires(!IsSame<RemoveCVReference<U>, KResultOr<T>>)
: m_have_storage(true)
{ {
new (&m_storage) T(move(value)); new (&m_storage) T(forward<U>(value));
m_have_storage = true;
} }
KResultOr(KResultOr&& other) KResultOr(KResultOr&& other)
{ {
m_is_error = other.m_is_error; m_is_error = other.m_is_error;
if (m_is_error) if (m_is_error) {
m_error = other.m_error; m_error = other.m_error;
else { } else {
if (other.m_have_storage) { if (other.m_have_storage) {
new (&m_storage) T(move(other.value())); new (&m_storage) T(move(other.value()));
m_have_storage = true; m_have_storage = true;
@ -96,9 +102,9 @@ public:
m_have_storage = false; m_have_storage = false;
} }
m_is_error = other.m_is_error; m_is_error = other.m_is_error;
if (m_is_error) if (m_is_error) {
m_error = other.m_error; m_error = other.m_error;
else { } else {
if (other.m_have_storage) { if (other.m_have_storage) {
new (&m_storage) T(move(other.value())); new (&m_storage) T(move(other.value()));
m_have_storage = true; m_have_storage = true;