ladybird/AK/TypeCasts.h
Timothy Flynn fc20e61e72 AK: Introduce an as_if<OutputType>() cast
We currently have a fair amount of code of the form:

    if (is<Child>(parent)) {
        auto& child = static_cast<Child&>(parent);

        if (child.foo()) {
        }
    }

This new cast allows us to instead write code of the form:

    if (auto* child = as_if<Child>(parent); child && child->foo()) {
    }

N.B. The name "as_if" was chosen because we are considering renaming
verify_cast to "as".

Co-authored-by: Tim Ledbetter <tim.ledbetter@ladybird.org>
2025-01-21 14:58:32 +01:00

76 lines
2 KiB
C++

/*
* Copyright (c) 2020-2021, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Assertions.h>
#include <AK/Concepts.h>
#include <AK/Forward.h>
#include <AK/Platform.h>
namespace AK {
template<typename OutputType, typename InputType>
ALWAYS_INLINE bool is(InputType& input)
{
static_assert(!SameAs<OutputType, InputType>);
if constexpr (requires { input.template fast_is<OutputType>(); }) {
return input.template fast_is<OutputType>();
}
return dynamic_cast<CopyConst<InputType, OutputType>*>(&input);
}
template<typename OutputType, typename InputType>
ALWAYS_INLINE bool is(InputType* input)
{
return input && is<OutputType>(*input);
}
template<typename OutputType, typename InputType>
ALWAYS_INLINE bool is(NonnullRefPtr<InputType> const& input)
{
return is<OutputType>(*input);
}
template<typename OutputType, typename InputType>
ALWAYS_INLINE CopyConst<InputType, OutputType>* verify_cast(InputType* input)
{
static_assert(IsBaseOf<InputType, OutputType>);
VERIFY(!input || is<OutputType>(*input));
return static_cast<CopyConst<InputType, OutputType>*>(input);
}
template<typename OutputType, typename InputType>
ALWAYS_INLINE CopyConst<InputType, OutputType>& verify_cast(InputType& input)
{
static_assert(IsBaseOf<InputType, OutputType>);
VERIFY(is<OutputType>(input));
return static_cast<CopyConst<InputType, OutputType>&>(input);
}
template<typename OutputType, typename InputType>
ALWAYS_INLINE CopyConst<InputType, OutputType>* as_if(InputType& input)
{
if (!is<OutputType>(input))
return nullptr;
return static_cast<CopyConst<InputType, OutputType>*>(&input);
}
template<typename OutputType, typename InputType>
ALWAYS_INLINE CopyConst<InputType, OutputType>* as_if(InputType* input)
{
if (!input)
return nullptr;
return as_if<OutputType>(*input);
}
}
#if USING_AK_GLOBALLY
using AK::as_if;
using AK::is;
using AK::verify_cast;
#endif